aaif-goose/goose · warning

Session has no messages

Error message

Session has no messages

What it means

Raised only for `--format markdown`: markdown export renders the conversation transcript, so session.conversation must be Some. Sessions that were created but never recorded messages (or migrated/imported files lacking the conversation field) have conversation = None and cannot be rendered as markdown. JSON and YAML export work because they serialize the whole session object.

Source

Thrown at crates/goose-cli/src/commands/session.rs:251

    let session_manager = SessionManager::instance();
    let session = match session_manager.get_session(&session_id, true).await {
        Ok(session) => session,
        Err(e) => {
            return Err(anyhow::anyhow!(
                "Session '{}' not found or failed to read: {}",
                session_id,
                e
            ));
        }
    };

    let output = match format.as_str() {
        "json" => serde_json::to_string_pretty(&session)?,
        "yaml" => serde_yaml::to_string(&session)?,
        "markdown" => {
            let conversation = session
                .conversation
                .ok_or_else(|| anyhow::anyhow!("Session has no messages"))?;
            export_session_to_markdown(conversation.user_visible_messages(), &session.name)
        }
        _ => return Err(anyhow::anyhow!("Unsupported format: {}", format)),
    };

    #[cfg(feature = "nostr")]
    if nostr {
        if format != "json" {
            return Err(anyhow::anyhow!(
                "Nostr session sharing only supports --format json"
            ));
        }
        if output_path.is_some() {
            return Err(anyhow::anyhow!(
                "Nostr session sharing cannot be combined with --output"
            ));
        }

View on GitHub (pinned to 3810898a74)

Solutions

  1. Export the same session as --format json or yaml (they do not require messages)
  2. Pick a session that actually has messages (`goose session list` shows activity)
  3. Send at least one message in the session before markdown export

Example fix

# before
goose session export <empty-session-id> --format markdown
# after
goose session export <empty-session-id> --format json
goose session export <session-with-messages> --format markdown
Defensive patterns

Strategy: validation

Validate before calling

let session = session_manager.get_session(&id, true).await?;
let format = if session_has_messages(&session) { "markdown" } else { "json" };

Type guard

fn session_has_messages(s: &Session) -> bool {
    s.conversation
        .as_ref()
        .is_some_and(|c| !c.user_visible_messages().is_empty())
}

Try / catch

match handle_session_export(id, None, "markdown".into(), false, vec![]).await {
    Err(e) if e.to_string() == "Session has no messages" => {
        handle_session_export(id, None, "json".into(), false, vec![]).await // fall back to json
    }
    other => other,
}

Prevention

When it happens

Trigger: `goose session export <id> --format markdown` on a session with zero messages; exporting a just-created session before any turn completes; importing a transcript that goose stored without a conversation payload.

Common situations: Testing export on a throwaway empty session; exporting immediately after `goose session start` before chatting; sessions created by headless/automation runs that errored out before writing messages.

Related errors


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