n8n-io/n8n · error · TaskTimeoutError

Task execution timed out after {task_timeout} seconds

Error message

Task execution timed out after {task_timeout} seconds

What it means

TaskTimeoutError is raised by TaskExecutor.execute_process when the forked Python subprocess is still alive after process.join(timeout=task_timeout) returns. The executor first attempts graceful termination via stop_process before raising, so by the time the error surfaces the child has already been signaled to stop. The {task_timeout} placeholder is the per-task ceiling (seconds) configured on the task runner.

Source

Thrown at packages/@n8n/task-runner-python/src/task_executor.py:231

        print_args: PrintArgs = []

        pipe_reader = PipeReader(read_conn.fileno(), read_conn)
        pipe_reader.start()

        try:
            try:
                process.start()
            except Exception as e:
                raise TaskSubprocessFailedError(-1, e)
            finally:
                write_conn.close()

            process.join(timeout=task_timeout)

            if process.is_alive():
                TaskExecutor.stop_process(process)
                raise TaskTimeoutError(task_timeout)

            if process.exitcode == SIGTERM_EXIT_CODE:
                raise TaskCancelledError()

            if process.exitcode == SIGKILL_EXIT_CODE:
                raise TaskKilledError()

            if process.exitcode != 0:
                assert process.exitcode is not None
                raise TaskSubprocessFailedError(process.exitcode)

            pipe_reader.join(timeout=task_timeout)

            if pipe_reader.is_alive():
                try:
                    read_conn.close()
                except Exception:
                    pass

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Inspect the Python snippet for loops, sleeps, or blocking I/O and add internal progress checks or shorter timeouts so the task finishes well under task_timeout.
  2. If the work is legitimately long, raise the task_timeout configuration for the task runner (e.g. TASK_RUNNER_TASK_TIMEOUT env / config) to a value with headroom above the worst observed run.
  3. Replace blocking calls (requests, input, socket reads) with timeout-bounded equivalents (requests.get(url, timeout=...), selectors) so the task fails fast instead of hanging until the ceiling.
  4. For CPU-bound work, move heavy processing into a worker pool with chunked progress reporting so partial results can be emitted before the ceiling.

Example fix

// before
import time
while True:
    do_work()
// after
import time
deadline = time.monotonic() + (task_timeout_seconds - 5)
while time.monotonic() < deadline:
    do_work()
Defensive patterns

Strategy: try-catch

Validate before calling

# No pre-check possible; instead bound work internally.
import time
def run_with_budget(fn, budget_seconds):
    deadline = time.monotonic() + budget_seconds
    while time.monotonic() < deadline:
        if not fn.step():
            break
    return fn.result()

Try / catch

from n8n_task_runner.errors import TaskTimeoutError
try:
    result = TaskExecutor.execute_process(proc, rc, wc, task_timeout, continue_on_fail=False)
except TaskTimeoutError as e:
    # task exceeded ceiling; surface a cancellation-style result
    return [{"json": {"error": f"task timed out: {e}"}}], [], 0

Prevention

When it happens

Trigger: A Python code task whose top-level execution (the forked process running the user's code) does not return within the configured task_timeout. Triggered by an infinite loop, a long sleep, a blocking socket read with no timeout, or a runaway computation in the user's Python snippet.

Common situations: User code calls time.sleep(very_large_number), runs a tight while True loop, performs a synchronous requests.get against a slow endpoint without a timeout, or processes a huge dataset in one shot. Also occurs when the runner is deployed on a CPU-constrained node and the default task_timeout is too low for legitimate work.

Understand the failure class

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/4da75b1666f1e294. Report an issue: GitHub.