All posts

Schedule Trigger in n8n: why the schedule stops firing after an update

You pushed a new version of the workflow through the public API, it is active, there are no errors — and the Schedule Trigger never fires.

PROCESS SCHEDULER — — — 0 registered jobs ACTIVATION VIA API RESPONSE POST …/activate → 200 "active": true a flag in the database
Short answer

Do not call deactivate before the update or activate after it. Push the new version with a single PUT /api/v1/workflows/{id} request straight into the active workflow — the scheduler rereads the schedule on its own. The active field in the public API is read-only, so there is no need to switch the workflow off. Switch it off and back on and you get 200, active: true, and a trigger that never fires.

Sections · 8

The workflow is green in the list, GET /api/v1/workflows/{id} returns "active": true, the Schedule Trigger holds a valid cron, there are no errors under Executions — and no executions either. A manual run works. Webhooks in the same workflow work. The schedule alone does not.

#What is actually going on

When a workflow is updated programmatically, the simplest route looks obvious: switch it off, push the new version, switch it back on. Roughly this:

curl -X POST "$BASE/api/v1/workflows/$ID/deactivate" -H "X-N8N-API-KEY: $KEY"
curl -X PUT  "$BASE/api/v1/workflows/$ID" -H "X-N8N-API-KEY: $KEY" \
     -H 'Content-Type: application/json' --data @workflow.json
curl -X POST "$BASE/api/v1/workflows/$ID/activate" -H "X-N8N-API-KEY: $KEY"

All three requests return 200. The last one returns the workflow object with "active": true. As far as the API is concerned, the job is done.

But a schedule trigger in n8n is not a flag in the database, it is a registered job in the process’s scheduler. Activating through the public API sets the flag, but it does not always restore that registration. The state in the database and the state in the scheduler drift apart, and from the outside the gap shows up nowhere: not in the workflow list, not in the API response, not in the logs.

#How to update a workflow properly

Push the new version with a single PUT straight into the active workflow, switching nothing off:

curl -X PUT "$BASE/api/v1/workflows/$ID" \
     -H "X-N8N-API-KEY: $KEY" \
     -H 'Content-Type: application/json' \
     --data @workflow.json

Here is why this works. In the public API the active field is read-only — it is not part of the PUT body, and the request does not change it. So updating an active workflow does not reset its state: it stays active. The scheduler picks up the changed schedule on its own.

We checked this: pushed a new schedule into an active workflow and waited for it to fire at the appointed minute, with no deactivation.

#How to check that the schedule is registered

The active flag confirms nothing. The only confirmation is an execution that actually happened. The simplest check is to set the schedule to the next minute, wait for it, and look at the list of executions:

# put the next minute into the Schedule Trigger cron, push with PUT, wait,
# then check whether an execution of type trigger has appeared
curl -s "$BASE/api/v1/executions?workflowId=$ID&limit=5" \
     -H "X-N8N-API-KEY: $KEY" \
  | jq -r '.data[] | "\(.id)  \(.mode)  \(.status)  \(.startedAt)"'

The field to look at is mode. A manual run gives manual, a webhook gives webhook, and only the schedule gives trigger. If after the update the list holds nothing but manual, the schedule is not registered — however many times the API answered active: true.

#What to do if the schedule has already stopped working

The Active toggle in the interface restores the scheduler’s state: switch it off by hand and back on. That defeats the idea of pushing automatically, but as a one-off procedure it works. After that, move to PUT without deactivation and the problem will not come back.

Restarting the n8n process itself also restores the registration, because on start n8n reads the schedules from the database again. If you are on Docker and a restart is cheap, that is quicker than hunting for the right workflow in the list.

#Why PUT suits generated workflows

A PUT replaces the workflow whole, node ids included. If you generate the JSON with a script and the node ids are random every time, each push rebuilds the connections and shows changes where nothing changed.

To avoid that, the node id is made deterministic — a hash of the name. Then a repeat push does not break the connections and shows only the real changes. There is a separate piece on how that works: n8n workflows in code.

Together this gives you a working loop: edit in the generator → PUT → check the executions. No deactivation, and nothing done by hand in the interface.

#Takeaways

  • A deactivate + activate sequence through the public API returns 200 and active: true, but the schedule can be left unregistered afterwards.
  • Update the active workflow with a single PUT — the active field in the public API is read-only anyway.
  • Check for an execution with mode: trigger, not for the flag.
  • The registration is restored by the Active toggle in the interface, or by restarting the process.
  • Deterministic node ids make a repeat push safe.

#Common questions

#Can you update an active workflow through the API without deactivating it?

Yes. The active field in the public API is read-only, so a PUT does not change the workflow’s state. It stays active, and the scheduler picks up the new schedule value on its own.

#Why does the API return active: true when the schedule is not working?

The active flag is stored in the database, while the schedule is handled by a registered job in the process’s scheduler. Those are two different states, and after an activation through the API they can drift apart. The API response shows you only the first of them.

#What is the quickest way to check that the trigger is registered?

Set the schedule to the next minute, wait for it, and look at GET /api/v1/executions. If no execution with mode: trigger has appeared, the trigger is not registered.

#Sources

weirflow — Business process automation. Published: August 11, 2026

Describe your situation

Tell us which process eats the most time. We will write back with what can be automated and roughly what it would cost.

Discuss a project
All posts