OrgKit / Guides / WorkflowRule empty

WorkflowRule returns zero rows in the Tooling API

Your migration checklist says "disable workflow rules." Your query returns nothing. Before you conclude the org is clean, work out which of three very different things just happened — because two of them mean automation is still armed.

Salesforce · Workflow Rules · Tooling API · Industries / Vlocity

{ "totalSize": 0, "done": true, "records": [] }

Do not read zero as "clean"

This is the whole point of the page. A count of zero can mean any of the following, and they demand opposite responses:

What happenedWhat you should do
The org really has no workflow rulesNothing. Move on to flows.
The query ran but excluded themFix the query and re-check.
The query failed and something swallowed the errorStop. Read the actual API response.

A tool that renders all three as "0" is actively dangerous during a migration, because it tells you automation is off when it may be running. If you are writing one, keep the empty case and the error case separate all the way to the UI.

Cause 1: the org migrated, and this is now normal

Salesforce ended support for Workflow Rules and Process Builder on 31 December 2025, with a long-signalled push toward Flow. Existing rules generally keep running, but no new investment is going into them and Salesforce's guidance is to migrate.

The practical consequence for anyone writing migration tooling in 2026: an empty workflow rule result is increasingly the correct answer. Plenty of orgs finished their migration and have genuinely none left. If your checklist still treats "zero workflow rules" as suspicious, the checklist is out of date.

Confirm it the boring way — Setup → Process Automation → Workflow Rules. If Setup shows an empty list too, the org is clean and your query was right.

Migration implication

If workflow rules are gone, the automation you actually need to disable before a data load is flows and triggers. Confirm what replaced them rather than assuming the org simply lost its automation.

Cause 2: the query, not the org

A plain query is the right diagnostic. Add no filters at all first:

-- Tooling API, no filters SELECT Id, Name, TableEnumOrId, Active FROM WorkflowRule

Then narrow. Two filter mistakes account for most false empties:

Run the unfiltered version once. If it returns rows, your filter was the problem and you now know exactly which one.

Cause 3: the call failed and you never saw it

This is the one that bites, and it is usually your own code's fault rather than Salesforce's. If the object isn't queryable in that org's configuration, or the composite request was malformed, Salesforce returns a non-200 with a real message — INVALID_TYPE, a malformed query, or an insufficient-access error. Any of these is informative. But a client that wraps the call in a broad try/catch and falls back to an empty array converts a useful error into a confident, wrong zero.

// the anti-pattern try { rules = await query('SELECT Id FROM WorkflowRule'); } catch (e) { rules = []; // the error is now invisible }
// what to do instead try { rules = await query('SELECT Id FROM WorkflowRule'); state = { kind: 'ok', rules }; } catch (e) { state = { kind: 'unavailable', reason: e.message }; }

Then render the two states differently: "0 workflow rules" versus "couldn't read workflow rules — reason." The second is honest and lets the user decide.

Truncated errors hide the answer

If you log or display API errors, don't truncate them to a short preview. Salesforce puts the actionable part — the field or object it objected to — at the end of the message. Cutting the string at 160 characters throws away the only useful part, and you end up guessing at a problem the API already explained.

Why Industries and Vlocity orgs surface this most

Anecdotally this is where the empty-or-erroring result shows up most often. Those orgs carry very large managed packages, a distinct feature mix, and frequently a different automation history from a standard CRM org.

The engineering conclusion is not to special-case the org type. Detecting "is this a Vlocity org" is fragile and will drift. Handle the three outcomes — rows, empty, error — distinctly on every org, and Industries orgs stop being a special case at all.

Frequently asked

Can I deactivate a workflow rule through the Tooling API?

Where the object is writable in your org, yes — a PATCH on the record with the full Metadata passed back through. As with validation rules, GET the complete Metadata first and modify it, rather than sending a partial object.

Why does a partial Metadata update silently do nothing?

The Tooling API treats Metadata as a whole-object write. Send a subset and you can get a 204 with no effective change. Always GET, mutate the returned object, PATCH it back.

Should I migrate workflow rules to Flow before a data migration?

Not as part of the same change window. Two large changes at once makes failure impossible to attribute. Do the data migration with what exists, then migrate the automation separately.

Does Setup show packaged workflow rules?

Yes, and packaged ones can't be deactivated in the subscriber org — same package boundary as packaged Apex triggers.

What is the fastest way to inventory all automation in an unfamiliar org?

Query each type separately, keep the counts per type, and record whether each query succeeded, returned empty, or failed. That three-state inventory is the artefact you actually want before touching anything.

Where OrgKit fits

SF Automation Switch inventories validation rules, flows, processes, triggers, and workflow rules in one pass, and reports "unavailable" separately from "none found" — precisely because reading zero as clean is how migrations go wrong. It snapshots the state before you change anything so the revert is exact.

Free, runs in the browser, nothing stored server-side.

Open SF Automation Switch

Related