{"record":{"id":"2bb5eb5285d1b693","repo":"n8n-io/n8n","slug":"process-was-forcefully-killed-sigkill","errorCode":null,"errorMessage":"Process was forcefully killed (SIGKILL)","messagePattern":"Process was forcefully killed \\(SIGKILL\\)","errorType":"exception","errorClass":"TaskKilledError","httpStatus":null,"severity":"critical","filePath":"packages/@n8n/task-runner-python/src/task_executor.py","lineNumber":237,"sourceCode":"        try:\n            try:\n                process.start()\n            except Exception as e:\n                raise TaskSubprocessFailedError(-1, e)\n            finally:\n                write_conn.close()\n\n            process.join(timeout=task_timeout)\n\n            if process.is_alive():\n                TaskExecutor.stop_process(process)\n                raise TaskTimeoutError(task_timeout)\n\n            if process.exitcode == SIGTERM_EXIT_CODE:\n                raise TaskCancelledError()\n\n            if process.exitcode == SIGKILL_EXIT_CODE:\n                raise TaskKilledError()\n\n            if process.exitcode != 0:\n                assert process.exitcode is not None\n                raise TaskSubprocessFailedError(process.exitcode)\n\n            pipe_reader.join(timeout=task_timeout)\n\n            if pipe_reader.is_alive():\n                try:\n                    read_conn.close()\n                except Exception:\n                    pass\n                raise TaskResultReadError(\n                    TimeoutError(f\"Pipe reader timed out after {task_timeout}s\")\n                )\n\n            if pipe_reader.error:\n                raise TaskResultReadError(pipe_reader.error)","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/task-runner-python/src/task_executor.py#L219-L255","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nimport pandas as pd\ndf = pd.read_csv('huge.csv')  # loads entire file, OOM risk\n// after\nimport pandas as pd\nfor chunk in pd.read_csv('huge.csv', chunksize=10000):\n    process(chunk)\n","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from n8n_task_runner.errors import TaskKilledError\ntry:\n    result = TaskExecutor.execute_process(proc, rc, wc, task_timeout, continue_on_fail=False)\nexcept TaskKilledError:\n    # likely OOM or unresponsive child; report and surface diagnostics\n    return [{\"json\": {\"error\": \"task force-killed (possible OOM)\"}}], [], 0\n","preventionTips":["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."],"tags":["python","task-runner","oom","signals","subprocess","memory"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}