n8n-io/n8n · error · TaskResultMissingError

Process completed but returned no result. This is likely an

Error message

Process completed but returned no result. This is likely an internal error.

What it means

TaskResultMissingError is raised when pipe_reader.pipe_message is None after a successful child exit and a successful reader join. The child finished with exit code 0 and the reader thread finished without error, but no message at all was written to the pipe. The message 'Process completed but returned no result' marks this as an internal-error condition rather than a user input problem.

Source

Thrown at packages/@n8n/task-runner-python/src/task_executor.py:258

                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)

            if pipe_reader.pipe_message is None:
                raise TaskResultMissingError()

            returned = pipe_reader.pipe_message

            if "error" in returned:
                error_msg = cast(PipeErrorMessage, returned)
                raise TaskRuntimeError(error_msg["error"])

            if "result" not in returned:
                raise TaskResultMissingError()

            result_msg = cast(PipeResultMessage, returned)
            result = result_msg["result"]
            print_args = result_msg.get("print_args", [])
            assert pipe_reader.message_size is not None
            result_size_bytes = pipe_reader.message_size

            return result, print_args, result_size_bytes

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Report as an internal bug: capture the runner version, the user snippet, and the child's stdout/stderr if surfaced; do not treat it as a user error.
  2. If you control the runner, verify the child-side entry point always reaches the result send on every code path, including early returns and exceptions caught inside the child.
  3. Reproduce with verbose child logging to confirm whether the child reached the result-send call.
  4. Check that no os._exit or sys.exit is being invoked inside the child before the result is sent.
Defensive patterns

Strategy: try-catch

Try / catch

from n8n_task_runner.errors import TaskResultMissingError
try:
    result = TaskExecutor.execute_process(proc, rc, wc, task_timeout, continue_on_fail=False)
except TaskResultMissingError as e:
    # internal-error path: capture diagnostics, do not blame user code
    report_internal_bug("child exited without sending result", exc=e)
    return [{"json": {"error": "internal: no result returned"}}], [], 0

Prevention

When it happens

Trigger: The child process ran to completion but never called the result-sending primitive (e.g. forgot to return, exited via os._exit(0) which skips finalizers/flush, or the result dispatch hook was patched out). It is almost always an internal bug in the runner harness or a sandboxing side effect, not user code.

Common situations: An internal regression where the child's main loop does not reach the send-result call; a sandboxing shim that overrides the result channel; a partial migration of the IPC protocol; a fork-server quirk where the worker exits 0 without dispatching.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/0d0e762086834318. Report an issue: GitHub.