From a490150512c8ad03f9fbebdf2bc4334921e49321 Mon Sep 17 00:00:00 2001 From: chengcong Date: Mon, 15 Jun 2026 19:44:04 +0800 Subject: [PATCH] Handle kernel dead status message in iopub polling When a kernel dies, the gateway server broadcasts an iopub status message with execution_state="dead". Previously this message was silently discarded because it doesn't match the current cell's parent_msg_id. Now _async_poll_output_msg checks for the dead status before filtering by parent_msg_id, and cancels task_poll_for_reply to trigger DeadKernelError in the main execution flow. This mirrors how _async_poll_kernel_alive handles kernel death detection. This is particularly important for Jupyter Gateway/Enterprise Gateway deployments where the kernel runs on a remote server and the local KernelManager may not detect death through other channels promptly. Co-Authored-By: Claude Opus 4.6 --- nbclient/client.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nbclient/client.py b/nbclient/client.py index f60361c..f637913 100644 --- a/nbclient/client.py +++ b/nbclient/client.py @@ -811,6 +811,10 @@ async def _async_poll_output_msg( assert self.kc is not None while True: msg = await ensure_async(self.kc.iopub_channel.get_msg(timeout=None)) + if msg["msg_type"] == "status" and msg["content"].get("execution_state") == "dead": + assert self.task_poll_for_reply is not None + self.task_poll_for_reply.cancel() + return if msg["parent_header"].get("msg_id") == parent_msg_id: try: # Will raise CellExecutionComplete when completed