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:
passView on GitHub (pinned to 5ac6606e81)
Solutions
- 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.
- 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.
- 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.
- 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
- Always pass an explicit task_timeout sized to the worst-case legitimate run plus headroom.
- For network calls inside user code, always set client-side timeouts smaller than task_timeout.
- Prefer continue_on_fail=True for non-critical tasks so a single timeout does not abort the workflow.
- Log task wall-clock times to detect slow drift before it hits the ceiling.
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Task timeout must be positive, got {task_timeout}
- Auto shutdown timeout must be non-negative, got {auto_shutdo
- Graceful shutdown timeout must be positive, got {graceful_sh
- Task subprocess exited with code -1
- Task was cancelled
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/4da75b1666f1e294.
Report an issue: GitHub.