{"record":{"id":"fdcb7c223eb2434d","repo":"n8n-io/n8n","slug":"task-was-cancelled","errorCode":null,"errorMessage":"Task was cancelled","messagePattern":"Task was cancelled","errorType":"exception","errorClass":"TaskCancelledError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/task-runner-python/src/task_executor.py","lineNumber":234,"sourceCode":"        pipe_reader = PipeReader(read_conn.fileno(), read_conn)\n        pipe_reader.start()\n\n        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                )","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/task-runner-python/src/task_executor.py#L216-L252","documentation":"TaskCancelledError is raised when the forked subprocess exited with SIGTERM_EXIT_CODE, meaning it received a termination signal and shut down cooperatively. This is distinct from TaskKilledError (SIGKILL) and TaskTimeoutError (still alive at the ceiling). The executor treats SIGTERM as an explicit cancellation rather than a crash.","triggerScenarios":"The task was cancelled mid-flight by an external SIGTERM: an operator or orchestrator (n8n execution abort, container stop, k8s pod termination) sent SIGTERM to the worker process group, or the parent runner invoked stop_process which escalates to SIGTERM before SIGKILL.","commonSituations":"User clicks 'Stop execution' on a running workflow whose Python task is in flight; the runner container is being drained/rolled; a higher-level timeout (e.g. workflow-level) cancels the task; a manual kill -TERM was issued against the worker PID.","solutions":["Treat cancellation as expected: catch TaskCancelledError at the caller and surface a user-visible 'cancelled' status rather than a generic failure.","If cancellations are unexpected, audit what is sending SIGTERM to the runner (orchestrator, deployment scripts, OOM killer is SIGKILL not SIGTERM so look elsewhere).","Make user Python code responsive to signals by checking a cancellation flag or registering a SIGTERM handler that exits promptly, so cancellation finishes quickly instead of waiting for the kill timeout.","Confirm the runner's stop_process escalation window (grace -> SIGTERM -> SIGKILL) is long enough for the task to release resources."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from n8n_task_runner.errors import TaskCancelledError\ntry:\n    result = TaskExecutor.execute_process(proc, rc, wc, task_timeout, continue_on_fail=False)\nexcept TaskCancelledError:\n    # cancellation is expected during aborts; treat as soft stop\n    return [], [], 0\n","preventionTips":["Distinguish cancellation from crash in the caller so users see the right status.","Keep SIGTERM grace windows long enough for the task to flush partial state.","Register a SIGTERM handler in user code that exits promptly.","Avoid ignoring SIGTERM in user code; that forces escalation to SIGKILL."],"tags":["python","task-runner","cancellation","signals","subprocess"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}