n8n-io/n8n · critical · TaskKilledError
Process was forcefully killed (SIGKILL)
Error message
Process was forcefully killed (SIGKILL)
What it means
TaskKilledError is raised when the forked subprocess exited with SIGKILL_EXIT_CODE. SIGKILL cannot be caught, so this always means the OS or the runner's stop_process escalation overrode the process. It indicates the process did not honor an earlier SIGTERM within the grace window, or the OS killed it directly (OOM killer).
Solutions
- Check runner/container memory limits and either raise the limit or reduce the working-set size in user code (stream instead of load-all, free intermediate buffers, use generators).
- Ensure user code does not install a SIGTERM handler that prevents shutdown; if it must handle SIGTERM, exit promptly rather than continuing.
- If using stop_process, confirm the grace window is shorter than task_timeout so SIGKILL only happens after a genuine hang, not a slow-but-progressing task.
- Inspect dmesg / kernel logs for OOM-kill entries on the task PID to distinguish runner-initiated kill from OS-initiated kill.
Example fix
// before
import pandas as pd
df = pd.read_csv('huge.csv') # loads entire file, OOM risk
// after
import pandas as pd
for chunk in pd.read_csv('huge.csv', chunksize=10000):
process(chunk)
Defensive patterns
Strategy: try-catch
Try / catch
from n8n_task_runner.errors import TaskKilledError
try:
result = TaskExecutor.execute_process(proc, rc, wc, task_timeout, continue_on_fail=False)
except TaskKilledError:
# likely OOM or unresponsive child; report and surface diagnostics
return [{"json": {"error": "task force-killed (possible OOM)"}}], [], 0
Prevention
- Size the container memory limit to exceed the peak working set of the largest task.
- Stream large datasets instead of loading them fully into memory.
- Do not install SIGTERM handlers that prevent graceful shutdown.
- Watch host memory pressure / dmesg for OOM-kill signatures.
When it happens
Trigger: stop_process escalated from SIGTERM to SIGKILL after the grace period because the child was unresponsive; or the kernel OOM killer selected the child because it exceeded the cgroup/host memory limit; or an external kill -9 was sent to the PID.
Common situations: User Python code allocates a large list/dataframe and hits the container memory limit; user code catches SIGTERM and ignores it (or is stuck in a C extension that can't be interrupted); the host is under memory pressure and the OOM killer reaps the task process.
Related errors
- Task was cancelled
- Task execution timed out after
- Task subprocess exited with code -1
- Task subprocess exited with code
- Auto shutdown timeout must be non-negative, got
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/2bb5eb5285d1b693.
Report an issue: GitHub.
Appendix: source
Thrown at packages/@n8n/task-runner-python/src/task_executor.py:237
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
raise TaskResultReadError(
TimeoutError(f"Pipe reader timed out after {task_timeout}s")
)
if pipe_reader.error:
raise TaskResultReadError(pipe_reader.error)View on GitHub (pinned to 5ac6606e81)