{"record":{"id":"d4d282a5d9dcbe1c","repo":"can1357/oh-my-pi","slug":"command-timed-out","errorCode":null,"errorMessage":"Command timed out","messagePattern":"Command timed out","errorType":"exception","errorClass":"PythonExecutionCancelledError","httpStatus":null,"severity":"warning","filePath":"packages/coding-agent/src/eval/py/executor.ts","lineNumber":254,"sourceCode":"\t) {\n\t\tthrow new PythonExecutionCancelledError(false);\n\t}\n\n\tconst deferred = Promise.withResolvers<PythonKernel>();\n\tconst replacement: SessionKernelReplacement = {\n\t\tgeneration,\n\t\tdeadlineMs: options.deadlineMs,\n\t\tpromise: deferred.promise,\n\t};\n\tsession.replacement = replacement;\n\tvoid (async () => {\n\t\ttry {\n\t\t\tconst remaining = getRemainingTimeoutMs(options.deadlineMs);\n\t\t\tawait kernel\n\t\t\t\t.shutdown(remaining !== undefined ? { timeoutMs: Math.max(0, remaining) } : undefined)\n\t\t\t\t.catch(() => undefined);\n\t\t\tif (replacement.deadlineMs !== undefined && replacement.deadlineMs <= Date.now()) {\n\t\t\t\tthrow new PythonExecutionCancelledError(true);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tcontext.sessions.get(session.sessionKey) !== session ||\n\t\t\t\tsession.generation !== generation ||\n\t\t\t\tsession.kernel !== kernel\n\t\t\t) {\n\t\t\t\tthrow new PythonExecutionCancelledError(false);\n\t\t\t}\n\t\t\tconst next = await startKernel(cwd, {\n\t\t\t\t...options,\n\t\t\t\tsignal: undefined,\n\t\t\t\tdeadlineMs: undefined,\n\t\t\t});\n\t\t\tif (\n\t\t\t\tcontext.sessions.get(session.sessionKey) !== session ||\n\t\t\t\tsession.generation !== generation ||\n\t\t\t\tsession.kernel !== kernel\n\t\t\t) {","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/eval/py/executor.ts#L236-L272","documentation":"After shutting down the old kernel, `replaceSessionKernel` checks the deadline: if `replacement.deadlineMs` is set and already passed (`deadlineMs <= Date.now()`), it throws `PythonExecutionCancelledError(true)` with message \"Command timed out\". This prevents starting a brand-new kernel on behalf of a command whose time budget has already expired.","triggerScenarios":"Kernel replacement taking longer than the caller's deadline (old kernel shutdown hung and consumed `remaining` time), so by the time a new kernel would start, the budget is exhausted.","commonSituations":"Shutdown of a wedged kernel process blocking until the deadline passes; very tight timeouts combined with slow process teardown; slow machine/filesystem making restart exceed the budget.","solutions":["Increase the command deadline/timeout for workloads that legitimately restart kernels","Reduce shutdown hang time (the code already bounds it with `getRemainingTimeoutMs`) — investigate why the old kernel shutdown stalls","Handle PythonExecutionCancelledError with timedOut=true distinctly: report timeout to the user instead of retrying"],"exampleFix":"// before\ncallPython(code, { deadlineMs: Date.now() + 1000 }); // too tight for restart\n// after\ncallPython(code, { deadlineMs: Date.now() + 30000 }); // budget covers kernel restart","handlingStrategy":"validation","validationCode":"const deadlineMs = Date.now() + budgetMs;\nif (budgetMs < MIN_RESTART_BUDGET_MS) {\n  throw new Error(`deadline ${budgetMs}ms too small for possible kernel restart`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await runPython(code, { deadlineMs });\n} catch (err) {\n  if (err instanceof PythonExecutionCancelledError && err.timedOut) {\n    // report timeout to user; optionally retry with a larger budget\n    throw new TimeoutError(`exceeded ${deadlineMs - (deadlineMs - budgetMs)}ms budget`);\n  }\n  throw err;\n}","preventionTips":["Give deadlines enough headroom to include a full kernel shutdown + restart","Avoid launching work whose remaining budget is nearly spent","Investigate kernel shutdown hangs that consume the budget"],"tags":["python","kernel","timeout","deadline"],"backgroundTag":"command-timeout","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}