{"record":{"id":"84af54bd9b93dd24","repo":"sigoden/aichat","slug":"no-session","errorCode":null,"errorMessage":"No session","messagePattern":"No session","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/config/mod.rs","lineNumber":1144,"sourceCode":"        Ok(())\n    }\n\n    pub fn session_info(&self) -> Result<String> {\n        if let Some(session) = &self.session {\n            let render_options = self.render_options()?;\n            let mut markdown_render = MarkdownRender::init(render_options)?;\n            let agent_info: Option<(String, Vec<String>)> = self.agent.as_ref().map(|agent| {\n                let functions = agent\n                    .functions()\n                    .declarations()\n                    .iter()\n                    .filter_map(|v| if v.agent { Some(v.name.clone()) } else { None })\n                    .collect();\n                (agent.name().to_string(), functions)\n            });\n            session.render(&mut markdown_render, &agent_info)\n        } else {\n            bail!(\"No session\")\n        }\n    }\n\n    pub fn exit_session(&mut self) -> Result<()> {\n        if let Some(mut session) = self.session.take() {\n            let sessions_dir = self.sessions_dir();\n            session.exit(&sessions_dir, self.working_mode.is_repl())?;\n            self.discontinuous_last_message();\n        }\n        Ok(())\n    }\n\n    pub fn save_session(&mut self, name: Option<&str>) -> Result<()> {\n        let session_name = match &self.session {\n            Some(session) => match name {\n                Some(v) => v.to_string(),\n                None => session\n                    .autoname()","sourceCodeStart":1126,"sourceCodeEnd":1162,"githubUrl":"https://github.com/sigoden/aichat/blob/82976d349ad97ac9aae0655ad631dace5e2a6385/src/config/mod.rs#L1126-L1162","documentation":"Raised by the session-rendering path (render_session / session render around src/config/mod.rs:1144) when asked to render session content but config.session is None — no session is currently active. The match on self.session falls through to the else branch and bails with 'No session'. Rendering an agent's messages requires a live session to read from.","triggerScenarios":"Calling `.session` display/render commands in the REPL before starting a session; calling the public render/session API on a fresh GlobalConfig; running a subcommand that displays session output outside any session context.","commonSituations":"New users running `.info`/session view before `.session start`; scripts that assume a persisted session exists after a CLI restart (sessions on disk are not auto-loaded into memory); a REPL restart wiping in-memory session state.","solutions":["Start a session first with `.session <name>` or `.session --new` before rendering","Load a saved session from the sessions directory if you meant to resume one","Guard the call: only render when an active session is present"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn session_active(cfg: &GlobalConfig) -> bool {\n    cfg.read().session.is_some()\n}","typeGuard":"fn active_session(cfg: &GlobalConfig) -> Option<String> {\n    cfg.read().session.as_ref().map(|s| s.name().to_string())\n}","tryCatchPattern":"match render_session(&config) {\n    Err(e) if e.to_string() == \"No session\" => eprintln!(\"start a session first: .session <name>\"),\n    other => other?,\n}","preventionTips":["Check session presence before render/display commands","Resume a saved session on REPL startup if your workflow depends on one","Document that on-disk session files are not auto-loaded"],"tags":["session","state","repl"],"backgroundTag":"invalid-state-transition","analyzedSha":"82976d349ad97ac9aae0655ad631dace5e2a6385","analyzedAt":"2026-09-09T18:33:06.139Z","contentChangedAt":"2026-09-09T18:33:06.139Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}