{"record":{"id":"d5cf30af59eb33b2","repo":"aaif-goose/goose","slug":"session-has-no-conversation","errorCode":null,"errorMessage":"Session {} has no conversation","messagePattern":"Session (.+?) has no conversation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose/src/agents/agent.rs","lineNumber":2078,"sourceCode":"                    .add_message(\n                        &session_config.id,\n                        &resolved_message.clone().with_visibility(false, true),\n                    )\n                    .await?;\n            }\n            Ok(None) => {\n                session_manager\n                    .add_message(&session_config.id, &user_message)\n                    .await?;\n            }\n        }\n        let session = session_manager\n            .get_session(&session_config.id, true)\n            .await?;\n        let conversation = session\n            .conversation\n            .clone()\n            .ok_or_else(|| anyhow::anyhow!(\"Session {} has no conversation\", session_config.id))?;\n\n        let needs_auto_compact = check_if_compaction_needed(\n            self.provider().await?.as_ref(),\n            &conversation,\n            None,\n            &session,\n        )\n        .await?;\n\n        let conversation_to_compact = conversation.clone();\n        let reply_span = tracing::Span::current();\n\n        Ok(Box::pin(async_stream::try_stream! {\n            for event in command_preamble {\n                yield event;\n            }\n\n            let final_conversation = if !needs_auto_compact {","sourceCodeStart":2060,"sourceCodeEnd":2096,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose/src/agents/agent.rs#L2060-L2096","documentation":"On the main reply path, after the user message is appended, agent.rs re-reads the session (get_session with include_messages) and expects Session.conversation to be Some so it can run compaction checks and build the reply context. This error means the session record exists but carries no conversation — the session was persisted without ever creating one.","triggerScenarios":"Replying in a session that was created empty (SessionManager create without an initial message) and whose add_message didn't yield a conversation; sessions produced by external tooling/import with conversation metadata absent; storage inconsistency where the message write and conversation field diverge.","commonSituations":"Programmatically created sessions (API/CLI flags) that skip the initial exchange and jump straight to agent.reply; resumed sessions whose file lost the conversation field.","solutions":["Initialize new sessions with a real first exchange (create via the normal chat entry point) before calling reply","Verify the session record actually contains the just-added user message; if not, storage is the problem","Recreate the session if its metadata is irreparably incomplete","Update goose — session-creation paths have been normalized across versions"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let session = session_manager.get_session(&session_id, true).await?;\nif session.conversation.is_none() {\n    anyhow::bail!(\n        \"session {session_id} was created without a conversation; initialize it with a first message\"\n    );\n}","typeGuard":"fn no_conversation(e: &anyhow::Error) -> bool {\n    e.to_string().contains(\"has no conversation\")\n}","tryCatchPattern":null,"preventionTips":["Always create sessions with an initial exchange instead of empty records","When importing/migrating sessions, ensure the conversation field is populated","Add an assertion on session.conversation in session-creation helpers"],"tags":["rust","goose","session","conversation","reply"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}