earendil-works/pi · error · Error
No messages to continue from
Error message
No messages to continue from
What it means
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.
Source
Thrown at packages/agent/src/agent.ts:368
async prompt(input: string | AgentMessage | AgentMessage[], images?: ImageContent[]): Promise<void> {
if (this.activeRun) {
throw new Error(
"Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.",
);
}
const messages = this.normalizePromptInput(input, images);
await this.runPromptMessages(messages);
}
/** Continue from the current transcript. The last message must be a user or tool-result message. */
async continue(): Promise<void> {
if (this.activeRun) {
throw new Error("Agent is already processing. Wait for completion before continuing.");
}
const lastMessage = this._state.messages[this._state.messages.length - 1];
if (!lastMessage) {
throw new Error("No messages to continue from");
}
if (lastMessage.role === "assistant") {
const queuedSteering = this.steeringQueue.drain();
if (queuedSteering.length > 0) {
await this.runPromptMessages(queuedSteering, { skipInitialSteeringPoll: true });
return;
}
const queuedFollowUps = this.followUpQueue.drain();
if (queuedFollowUps.length > 0) {
await this.runPromptMessages(queuedFollowUps);
return;
}
throw new Error("Cannot continue from message role: assistant");
}
View on GitHub (pinned to 4af9d21d3b)
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.
Example fix
// before
const agent = new Agent({ streamFn });
await agent.continue(); // throws: no messages
// after
await agent.prompt("hello");
await agent.continue(); Defensive patterns
Strategy: validation
Validate before calling
if (agent.state.messages.length === 0) {
await agent.prompt(seedMessage);
} else {
await agent.continue();
} Type guard
function hasTranscript(agent: Agent): boolean {
return agent.state.messages.length > 0;
} Try / catch
try {
await agent.continue();
} catch (err) {
if (err instanceof Error && err.message === "No messages to continue from") {
await agent.prompt("let's start");
} else {
throw err;
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Agent is already processing. Wait for completion before cont
- Cannot continue from message role: assistant
- Cannot continue: no messages in context
- Cannot continue from message role: assistant
- Agent is already processing. Wait for completion before rese
AI-assisted analysis of earendil-works/pi@4af9d21d3b (2026-08-24).
Data as JSON: /api/errors/cadf1c89b7e1fb5c.
Report an issue: GitHub.