Schedule Trigger silently stops firing after several days (Kubernetes + queue mode)

Describe the problem/error/question

I have a workflow that uses a Schedule Trigger and runs multiple times per day. After several days of working correctly, the workflow simply stops triggering. There are no failed executions and no error messages in the logs. The workflow remains active, but the scheduled executions no longer start.

During troubleshooting, I noticed that if I reduce the number of scheduled runs per day, the workflow continues working for a few more days before eventually stopping again. This makes me think the issue may be related to the scheduler, queue mode, or some resource limitation that accumulates over time.

Has anyone seen Schedule Trigger workflows silently stop in a Kubernetes deployment running in queue mode?

What is the error message (if any)?

There is no error message. The Schedule Trigger just stops firing.

Please share your workflow

The issue is not specific to a particular workflow. It happens with workflows that start with a Schedule Trigger and execute successfully until the trigger stops firing.

Schedule Trigger → (various nodes)

Share the output returned by the last node

There is no output when the issue occurs because the workflow never starts. When it does run, the workflow completes successfully.

Information on your n8n setup

  • n8n version: Helm chart n8n version 1.16.39 (please let me know if the actual application version is more relevant)
  • Database: PostgreSQL (external)
  • n8n EXECUTIONS_PROCESS setting: Queue mode
  • Running n8n via: Kubernetes using the Community Helm Chart
  • Operating system: Kubernetes cluster (Linux nodes)

Relevant configuration

redis:
  enabled: true

worker:
  mode: queue

webhook:
  mode: queue
  url: https://<my-domain>

db:
  type: postgresdb

externalPostgresql:
  host: <external-postgres>

Additional observations:

  • The workflows stop without any errors or failed executions.
  • Reducing the number of scheduled executions per day delays the issue but does not eliminate it.
  • Restarting the deployment restores the Schedule Trigger temporarily.
  • Redis is enabled and PostgreSQL is external.

Could this be related to queue mode, leader election, or the scheduler process in a multi-pod Kubernetes deployment?

Hi @thun

There is a documented issue (referenced in GitHub issues #30220 and #30256) where the Schedule Trigger silently stops firing after a certain number of executions (often around 700+ ticks for high-frequency workflows).

  • The Symptom: The workflow remains “Active” in the UI, manual executions work perfectly, but the automated trigger simply stops.
  • The Cause: A recursion/stack overflow error occurs in observable-object.ts during the trigger’s activation logic.
  • Crucial Detail: This error does not appear in the Workflow Execution logs because the crash happens in the scheduler’s internal loop before an execution is even created. It only appears in the stdout/stderr logs of the n8n Main container​.

Another known issue (#28423) involved the Schedule Trigger using a strict equality check (===) to determine if it was time to fire.

  • The Symptom: If the main process restarts or a leadership change occurs exactly when a trigger was supposed to fire, the lastExecution timestamp becomes “stale.”
  • The Cause: Because of the strict check, the scheduler would wait for the exact next tick. If the state was corrupted or missed, the workflow could be silently blocked for days or weeks.
  • The Fix: This was updated to an “elapsed-time” check (>=) to allow the scheduler to “self-heal” and fire immediately if it detects a missed window.

In queue mode, the Schedule Trigger is owned exclusively by the Main process (Leader).

  • Ghost Triggers: If your Helm chart is configured to allow more than one replica of the main process (or if an old pod persists during a rolling update), you can encounter “ghost triggers” or registration conflicts in Redis that eventually wedge the scheduler.
  • Worker Role: If worker pods are accidentally running the n8n start command instead of n8n worker, they will attempt to act as main processes, competing for the scheduler and causing erratic behavior.

Does any of these apply?

Can you do the following as well?

  1. Check Container Logs (Not UI Logs): Inspect the logs of your n8n main pod using kubectl logs <pod-name>. Search specifically for the string: RangeError: Maximum call stack size exceeded If you see this, you have confirmed the observable-object bug.

  2. Verify Main Pod Replicas: Ensure that your main deployment is strictly set to replicas: 1. In queue mode, having multiple mains without a robust leader election setup often leads to scheduler instability.

  3. Verify Worker Commands: Check the args or command section of your worker pods. They must be running: n8n worker (and NOT n8n start).

  4. Update n8n Version: The fixes for both the RangeError and the “Self-healing” scheduler were rolled out in recent updates (specifically addressed in versions around 2.20.9 and later in the @next branch, and backported to stable). Since you are on 1.16.39, you are likely running a version susceptible to these bugs. Updating to the latest stable release is the primary recommended fix.

Thanks for the response!

I viewed the main pod logs and saw alot of “Maximum call stack size exceeded”. I realized that I am some versions behind, I will try to update to newer versions and see if that help.

Thanks!

Good that you confirmed the ‘Maximum call stack size exceeded’ - that’s the bug from #30220. One thing to double-check in your Helm values before and after upgrading: replicaCount for the main deployment must be exactly 1. Running more than 1 main replica causes scheduler registration conflicts in Redis that can reproduce the same silent-stop symptom even after upgrading. Workers can scale freely, but main stays at 1.

Glad the log grep confirmed it — a wall of “Maximum call stack size exceeded” in the main pod is the #30220 tick-accumulation bug, and it matches your own clues exactly: fewer runs/day = longer to hit the limit, and a restart resets the counter to zero. The upgrade is the right fix, and nguyenthieutoan’s replicaCount: 1 check is worth doing in the same pass. One small thing while you’re choosing what to upgrade to: “1.16.39” is the Helm chart version, not the n8n app version — they’re numbered independently, so check what your image.tag actually resolves to and target the latest stable app version, not a chart number.

The part I’d flag because it outlives the upgrade: this failure class is invisible to n8n by design. No execution is ever created, so the Error Trigger never fires — there’s nothing to attach an error to. That’s why it ran silently for days. Even fully patched, a scheduler that “just stops, Active in the UI, no error” is something you’ll always learn about late, from a human noticing missing data. The durable fix is an external dead-man’s-switch: have the scheduled workflow push a heartbeat on every successful run (a Redis key with a TTL, a timestamped row, or a ping to a healthchecks-style monitor), and have something independent of n8n alert when the heartbeat goes stale. That turns “silently stopped for days” into “alerted in minutes,” whatever the root cause turns out to be next time.

If the upgrade doesn’t fully cure it — you’ve confirmed the RangeError, but if it still goes quiet on a patched version with replicas: 1 and workers genuinely running n8n worker — that’s the deployment-specific branch, and I’m happy to help you dig into it here.

One follow up before this thread closes, because there is a Kubernetes specific detail the fixes above do not cover, and it explains why this failure is so quiet on your cluster in particular.

Your liveness probe cannot see this failure. The n8n health endpoint answers from the web server, and the web server is fine while the scheduler loop is wedged, so Kubernetes keeps reporting a healthy pod and never restarts it. That is why the outage lasts days: the one mechanism built to restart a broken pod is reading a signal that does not exercise the broken component. Process health and scheduler health are different things, and every probe you currently have measures the first one.

Since a restart reliably restores the trigger, you can close the gap while you plan the upgrade with a canary: one trivial scheduled workflow that does nothing but write a timestamp somewhere cheap every few minutes, a Redis key, a Postgres row, or a ping to a free monitor like Healthchecks.io. When the timestamp goes stale, the scheduler is wedged regardless of what the health endpoint says. If you want it fully automatic, a small CronJob that checks the canary’s freshness and does a rollout restart of the main deployment when it goes stale turns a multi day outage into a few minutes of blip, which is an acceptable stopgap for a bug that only the upgrade actually fixes.

Two checks worth doing at the next wedge, before restarting, so the upgrade decision is grounded. Grab the main pod logs and search for RangeError: Maximum call stack size exceeded, as kjooleng said. And do the tick math: your own observation that fewer runs per day delays the failure is exactly what a ticks threshold bug predicts, so if runs per day multiplied by days to failure comes out roughly constant across your incidents, you have the confirmation without even waiting for the log line.