{"record":{"id":"058b8a4ba78bb996","repo":"can1357/oh-my-pi","slug":"cannot-continue-no-messages-in-context","errorCode":null,"errorMessage":"Cannot continue: no messages in context","messagePattern":"Cannot continue: no messages in context","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/agent-loop.ts","lineNumber":595,"sourceCode":"\n/**\n * Continue an agent loop from the current context without adding a new message.\n * Used for retries - context already has user message or tool results.\n *\n * **Important:** The last message in context must convert to a `user` or `toolResult` message\n * via `convertToLlm` — except for an assistant tail with unpaired runnable\n * tool calls (see {@link unpairedToolCallTail}), which resumes by executing\n * those calls first. Any other assistant tail is rejected here; other invalid\n * tails cannot be validated since `convertToLlm` is only called once per turn.\n */\nexport function agentLoopContinue(\n\tcontext: AgentContext,\n\tconfig: AgentLoopConfig,\n\tsignal?: AbortSignal,\n\tstreamFn?: StreamFn,\n): EventStream<AgentEvent, AgentMessage[]> {\n\tif (context.messages.length === 0) {\n\t\tthrow new Error(\"Cannot continue: no messages in context\");\n\t}\n\n\tif (context.messages[context.messages.length - 1].role === \"assistant\" && !unpairedToolCallTail(context.messages)) {\n\t\tthrow new Error(\"Cannot continue from message role: assistant\");\n\t}\n\n\tconst stream = createAgentStream();\n\n\t(async () => {\n\t\tconst newMessages: AgentMessage[] = [];\n\t\tconst currentContext: AgentContext = { ...context, messages: [...context.messages] };\n\n\t\tstream.push({ type: \"agent_start\" });\n\n\t\ttry {\n\t\t\tawait runLoop(currentContext, newMessages, config, signal, stream, streamFn);\n\t\t} catch (err) {\n\t\t\tstream.fail(err);","sourceCodeStart":577,"sourceCodeEnd":613,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/agent/src/agent-loop.ts#L577-L613","documentation":"agentLoopContinue continues an existing conversation by re-entering the agent loop with the context's message history. If context.messages is empty there is nothing to continue from, so it throws immediately (synchronously from the EventStream factory). This is a programmer/usage error: continue was called on a fresh or reset context instead of after at least one message.","triggerScenarios":"Calling agentLoopContinue(context, config) (via stream) with a brand-new AgentContext, a context that was cleared, or before any user message was pushed.","commonSituations":"Resuming a session file that failed to load (messages never restored); calling continue on a newly constructed agent instead of prompt/first turn; error-recovery paths that retry continue after the context was rebuilt empty.","solutions":["Use the initial-prompt entrypoint (agentLoop / prompt) instead of continue when the context has no messages.","Restore the message history before continuing (reload session state into context.messages).","Guard the call site: only invoke continue when context.messages.length > 0."],"exampleFix":"// before\nawait agentLoopContinue(context, config);\n// after\nif (context.messages.length === 0) {\n  await agentLoop(context, [userMessage], config);\n} else {\n  await agentLoopContinue(context, config);\n}","handlingStrategy":"validation","validationCode":"if (context.messages.length === 0) {\n  return agentLoop(context, [initialUserMessage], config);\n}\nreturn agentLoopContinue(context, config);","typeGuard":"function canContinue(context: AgentContext): boolean {\n  return context.messages.length > 0;\n}","tryCatchPattern":"try {\n  return agentLoopContinue(context, config);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"no messages in context\")) {\n    return agentLoop(context, [initialUserMessage], config);\n  }\n  throw err;\n}","preventionTips":["Only call continue on contexts restored from a saved session or after a completed turn.","Verify session load actually populated messages before resuming.","Route fresh contexts to the prompt/initial-loop entrypoint."],"tags":["agent-loop","usage-error","empty-context"],"backgroundTag":"empty-message-context","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}