Remove task runner from n8nio/n8n docker image

Describe the problem/error/question

I am trying to migrate my n8n Queue Mode setup on Railway from v1.x to v2.0.0. Since v2.0 removes the internal task runner, I set up External Task Runners using the n8nio/runners:2.0.0 image as sidecars.

My setup consists of 6 main services in Railway:

  1. Primary (n8nio/n8n:2.0.0)

  2. Worker (n8nio/n8n:2.0.0 running n8n worker)

  3. Task Runner for Primary (n8nio/runners:2.0.0)

  4. Task Runner for Worker (n8nio/runners:2.0.0)

  5. Postgres (db)

  6. Redis

Architecture & Config:

  • Primary has:

    • N8N_RUNNERS_ENABLED=true
      
      N8N_RUNNERS_MODE=external
      
      N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
      
  • Task Runner (Primary) connects to:

    • N8N_RUNNERS_TASK_BROKER_URI=http://${{Primary.RAILWAY_PRIVATE_DOMAIN}}:5679
      
  • Worker has similar config to Primary.

  • Task Runner (Worker) connects to:

    • N8N_RUNNERS_TASK_BROKER_URI=http://${{Worker.RAILWAY_PRIVATE_DOMAIN}}:5679
      

The Issue: Despite the logs on the Primary instance showing that runners are registering (

Registered runner "launcher-javascript" ...

), my workflows containing Code Nodes do not execute. They get stuck or queued indefinitely.

Specifically, on the Worker side, the Task Runner logs often show:

[launcher:js] Waiting for launcher's task offer to be accepted...
[launcher:js] Waiting for task broker to be ready...

It seems like the handshake happens, but the actual task execution fails to route correctly in the Railway private network environment.

What is the error message (if any)?

In the Worker's Task Runner logs:

INFO  [launcher:js] Starting launcher goroutine...

INFO  [launcher:js] Waiting for task broker to be ready...

INFO  [launcher:js] Waiting for launcher's task offer to be accepted...

In the Primary logs (showing successful registration but no execution):

Registered runner "launcher-javascript" (954eda98a81d248f) 

Registered runner "launcher-python" (be643b2515650863) 

Enqueued execution 1 (job 1)

... (Execution hangs here)

Information on your n8n setup

  • n8n version: 2.0.0

  • Database (default: SQLite): Postgres

  • n8n EXECUTIONS_PROCESS setting (default: own, main): queue

  • Running n8n via (Docker, npm, n8n cloud, desktop app): Railway (Docker)

  • Operating system: Linux

can anyone help here?

Hey @alhassan23, it’s a long shot as I imagine you just left it our for brevity, but have you got N8N_RUNNERS_AUTH_TOKEN configured on all services?

hi @alhassan23 !

One additional thing to check beyond authentication is the runner topology in queue mode.
In n8n 2.0, external task runners should connect only to the Primary instance (the task broker), not to individual Workers.

Workers are only responsible for pulling jobs from Redis, while the Primary coordinates runner task offers.
Pointing runners directly at Workers can result in runners registering but tasks never being accepted, which matches the behavior you’re seeing.

external task runners should connect only to the Primary instance (the task broker), not to individual Workers.

Is it only related to 2.x? What is your source @tamy.santos ?

I have the similar problem and I found in docs this:

When using Queue mode, each worker needs to have its own sidecar container for task runners.

In addition, if OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=false, then your main instance will run manual executions and needs its own sidecar container for task runners as well.

Source:

I see one difference in my case launcher is registered and right after that (less than 0.5s) is deregistered…

image

I messaged Tamy about that when originally posted as I was having problems with my runners and thought it was down to running brokers on my workers. However I since found the problem was to do with my k8s hosting network connectivity and I have been running brokers on my workers with no problem since. There’s also the below (my emphasis) in this documentation:

The n8n instance (main and worker) acts as the broker. The Code node in this case is the task requester.

Regarding the deregistration - I think that’s a normal part of the launcher/broker/runner lifecycle:

Once the launcher is started, it connects to the n8n instance via HTTP and then via websocket, registers itself as a runner with the task broker, and sends the task broker a non-expiring offer to run a task.

This flow is called the handshake. The handshake will complete only when a task needs to be run, i.e. only once the task broker sends the launcher (registered as a runner) the broker’s acceptance of the launcher’s offer to run a task.

The launcher itself cannot run a task, so once the launcher receives an acceptance from the broker, the launcher requests the broker to defer the task, disconnects from the task broker, and launches a task runner as a separate process.

from here.

Thanks for the answer.

Your quote:

The n8n instance (main and worker) acts as the broker. The Code node in this case is the task requester.

Is before the one I pasted:

When using Queue mode, each worker needs to have its own sidecar container for task runners.

In addition, if OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=false, then your main instance will run manual executions and needs its own sidecar container for task runners as well.

I believe that means:

IF OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=falseTHEN broker -> main + worker
IF ELSE OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=trueTHEN broker -> (ONLY)worker

Which means that in case where “OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true" we need a sidecar container with task runner only for worker.

Tell me if I am wrong, please?

That’s what I understand it to mean, yes. I have OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERSset to true and have no sidecar container with my main instance and haven’t witnessed any problems.

I have also raised a feature request to be able to disable the broker as I don’t think it’s required to be running on main in this configuration.

That’s what I understand it to mean, yes. I have OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERSset to true and have no sidecar container with my main instance and haven’t witnessed any problems.

I have also raised a feature request to be able to disable the broker as I don’t think it’s required to be running on main in this configuration.