aaif-goose/goose · error

No user message

Error message

No user message

What it means

reply() takes the last message in self.messages as the user turn to send to the provider. When the message list is empty there is no last element, so it fails with 'No user message' before any provider call is made.

Source

Thrown at crates/goose-cli/src/session/mod.rs:1440

    async fn process_agent_response(
        &mut self,
        interactive: bool,
        cancel_token: CancellationToken,
    ) -> Result<()> {
        let is_json_mode = self.output_format == "json";
        let is_stream_json_mode = self.output_format == "stream-json";

        let session_config = SessionConfig {
            id: self.session_id.clone(),
            schedule_id: self.scheduled_job_id.clone(),
            max_turns: self.max_turns,
            retry_config: self.retry_config.clone(),
        };
        let user_message = self
            .messages
            .last()
            .ok_or_else(|| anyhow::anyhow!("No user message"))?;

        let cancel_token_interrupt = cancel_token.clone();
        let handle = tokio::spawn(async move {
            if ctrl_c().await.is_ok() {
                cancel_token_interrupt.cancel();
            }
        });
        let _drop_handle = AbortOnDropHandle::new(handle);

        let mut stream = self
            .agent
            .reply(
                user_message.clone(),
                session_config.clone(),
                Some(cancel_token.clone()),
            )
            .await?;

View on GitHub (pinned to 3810898a74)

Solutions

  1. Push a user prompt into session.messages before invoking reply
  2. For goose run, supply the prompt via flags/args so the session starts non-empty
  3. If building on the API, assert !messages.is_empty() as a precondition

Example fix

// before
let reply = session.reply(&provider, cancel_token).await?;
// after
session.add_message(Message::user().with_text(prompt.clone()));
let reply = session.reply(&provider, cancel_token).await?;
Defensive patterns

Strategy: validation

Validate before calling

assert!(
    !session.messages.is_empty(),
    "reply() requires at least one message; add the user prompt first"
);

Prevention

When it happens

Trigger: Headless or recipe paths (goose run, resumed sessions, scheduled jobs, custom harnesses) that call reply before any user message was pushed into the session.

Common situations: Recipes without an initial prompt; resumed sessions whose persisted history is empty; integrations constructing a CliSession and calling reply directly without adding a message.

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/58532a1ea647ed2d. Report an issue: GitHub.