{"record":{"id":"cadf1c89b7e1fb5c","repo":"earendil-works/pi","slug":"no-messages-to-continue-from","errorCode":null,"errorMessage":"No messages to continue from","messagePattern":"No messages to continue from","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/agent.ts","lineNumber":368,"sourceCode":"\tasync prompt(input: string | AgentMessage | AgentMessage[], images?: ImageContent[]): Promise<void> {\n\t\tif (this.activeRun) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.\",\n\t\t\t);\n\t\t}\n\t\tconst messages = this.normalizePromptInput(input, images);\n\t\tawait this.runPromptMessages(messages);\n\t}\n\n\t/** Continue from the current transcript. The last message must be a user or tool-result message. */\n\tasync continue(): Promise<void> {\n\t\tif (this.activeRun) {\n\t\t\tthrow new Error(\"Agent is already processing. Wait for completion before continuing.\");\n\t\t}\n\n\t\tconst lastMessage = this._state.messages[this._state.messages.length - 1];\n\t\tif (!lastMessage) {\n\t\t\tthrow new Error(\"No messages to continue from\");\n\t\t}\n\n\t\tif (lastMessage.role === \"assistant\") {\n\t\t\tconst queuedSteering = this.steeringQueue.drain();\n\t\t\tif (queuedSteering.length > 0) {\n\t\t\t\tawait this.runPromptMessages(queuedSteering, { skipInitialSteeringPoll: true });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst queuedFollowUps = this.followUpQueue.drain();\n\t\t\tif (queuedFollowUps.length > 0) {\n\t\t\t\tawait this.runPromptMessages(queuedFollowUps);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthrow new Error(\"Cannot continue from message role: assistant\");\n\t\t}\n","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/earendil-works/pi/blob/4af9d21d3b4d664e4a29fcabfec85171077248e3/packages/agent/src/agent.ts#L350-L386","documentation":"Agent.continue() means 'generate the next assistant turn from the existing transcript', so it reads the last message of agent.state.messages and throws when there is none. A freshly constructed Agent (or one whose initialState.messages is empty) has nothing to resume, and the error fires before the loop is entered. Seed the transcript with prompt() first.","triggerScenarios":"Calling continue() on a new Agent before any prompt(); constructing Agent with initialState whose messages array is empty or failed to load; continuing after an aborted first prompt where no message was committed.","commonSituations":"Auto-continue/retry logic running after a startup failure; a 'continue' control enabled before the first user message; persistence loaders that silently return an empty array.","solutions":["Call agent.prompt(...) first to seed the transcript; only continue once at least one message exists.","When restoring from persistence, verify agent.state.messages.length > 0 before enabling continue.","Guard retry logic so it only continues when a previous turn actually left messages behind."],"exampleFix":"// before\nconst agent = new Agent({ streamFn });\nawait agent.continue(); // throws: no messages\n\n// after\nawait agent.prompt(\"hello\");\nawait agent.continue();","handlingStrategy":"validation","validationCode":"if (agent.state.messages.length === 0) {\n  await agent.prompt(seedMessage);\n} else {\n  await agent.continue();\n}","typeGuard":"function hasTranscript(agent: Agent): boolean {\n  return agent.state.messages.length > 0;\n}","tryCatchPattern":"try {\n  await agent.continue();\n} catch (err) {\n  if (err instanceof Error && err.message === \"No messages to continue from\") {\n    await agent.prompt(\"let's start\");\n  } else {\n    throw err;\n  }\n}","preventionTips":["Seed every conversation with prompt() before any continue call.","Disable continue controls until the transcript is non-empty.","Validate persisted/initial messages arrays before constructing the Agent."],"tags":["agent","continue","empty-transcript","precondition"],"backgroundTag":"empty-conversation-history","analyzedSha":"4af9d21d3b4d664e4a29fcabfec85171077248e3","analyzedAt":"2026-08-24T13:07:14.692Z","schemaVersion":2},"datasetVersion":"2026-08-24T17:17:21.512Z"}