{"record":{"id":"0519865e2dc469b9","repo":"n8n-io/n8n","slug":"task-subprocess-exited-with-code-1","errorCode":null,"errorMessage":"Task subprocess exited with code -1","messagePattern":"Task subprocess exited with code -1","errorType":"exception","errorClass":"TaskSubprocessFailedError","httpStatus":null,"severity":"critical","filePath":"packages/@n8n/task-runner-python/src/task_executor.py","lineNumber":223,"sourceCode":"    def execute_process(\n        process: ForkServerProcess,\n        read_conn: PipeConnection,\n        write_conn: PipeConnection,\n        task_timeout: int,\n        continue_on_fail: bool,\n    ) -> tuple[Items, PrintArgs, int]:\n        \"\"\"Execute a subprocess for a Python code task.\"\"\"\n\n        print_args: PrintArgs = []\n\n        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)","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/task-runner-python/src/task_executor.py#L205-L241","documentation":"Thrown by TaskExecutor.execute_process when process.start() raises an exception, indicating the Python subprocess for a code task could not be launched at all. The exit code is set to -1 (a sentinel, not a real OS exit code) and the original exception is chained. This is distinct from a subprocess that starts but then crashes (which would have a real exit code).","triggerScenarios":"The multiprocessing forkserver process fails to start. Common causes include the forkserver context being unavailable, the target function failing to import, the Pipe being broken before start(), or OS-level resource limits preventing process creation. The try/except around process.start() catches any Exception and wraps it in TaskSubprocessFailedError(-1, e).","commonSituations":"The Python runtime or required modules are missing or misconfigured in the subprocess environment. Resource exhaustion (too many processes, out of memory) preventing fork/spawn. The forkserver process crashed and cannot accept new processes. A broken pipe or serialization error when the runner tries to pass items to the subprocess. Incompatible Python version or missing shared libraries.","solutions":["Check the chained exception (the second argument to TaskSubprocessFailedError) for the root cause — it contains the original error from process.start().","Verify the Python environment is intact: correct Python version, required packages installed, no import errors in the target module.","Check system resource limits: max processes (ulimit -u), available memory, file descriptor limits.","If the forkserver is in a bad state, restart the runner process to get a fresh multiprocessing context.","Look at runner logs for earlier errors that may have corrupted the forkserver state."],"exampleFix":"# This is an infrastructure error, not a code fix.\n# Check the chained exception for root cause:\n\n# In runner logs, look for:\n# TaskSubprocessFailedError: Task subprocess exited with code -1\n# Caused by: <original exception from process.start()>\n\n# Common fixes:\n# 1. Restart the runner: kill the runner process and let n8n respawn it\n# 2. Check Python environment: python3 -c 'import task_executor'\n# 3. Check resource limits: ulimit -a\n# 4. Verify no missing shared libraries: ldd $(which python3)","handlingStrategy":"try-catch","validationCode":"import sys, importlib\n\ndef verify_runner_environment() -> bool:\n    \"\"\"Check that the subprocess can import its target.\"\"\"\n    try:\n        importlib.import_module('task_executor')\n        return True\n    except ImportError as e:\n        print(f'Runner environment broken: {e}')\n        return False\n\nif not verify_runner_environment():\n    sys.exit(1)","typeGuard":null,"tryCatchPattern":"from task_executor import TaskSubprocessFailedError, TaskTimeoutError, TaskCancelledError\n\ntry:\n    items, print_args, exit_code = TaskExecutor.execute_process(\n        process, read_conn, write_conn, task_timeout, continue_on_fail\n    )\nexcept TaskSubprocessFailedError as e:\n    if e.exit_code == -1:\n        logger.critical('Subprocess failed to start', exc_info=e.original)\n        # restart the runner or fall back to internal execution\n    else:\n        logger.error(f'Subprocess exited with code {e.exit_code}')","preventionTips":["Monitor runner process health and restart on crash.","Verify the Python environment and all dependencies are installed before starting the runner.","Set appropriate resource limits (ulimit) to prevent fork failures.","Log chained exceptions to capture the root cause of subprocess start failures.","Use a process manager (systemd, supervisor) to auto-restart the runner on failure."],"tags":["task-runner","python","subprocess","infrastructure","runtime-error"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}