sigoden/aichat · error

No session

Error message

No session

What it means

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.

Solutions

  1. Start a session first with `.session <name>` or `.session --new` before rendering
  2. Load a saved session from the sessions directory if you meant to resume one
  3. Guard the call: only render when an active session is present
Defensive patterns

Strategy: validation

Validate before calling

fn session_active(cfg: &GlobalConfig) -> bool {
    cfg.read().session.is_some()
}

Type guard

fn active_session(cfg: &GlobalConfig) -> Option<String> {
    cfg.read().session.as_ref().map(|s| s.name().to_string())
}

Try / catch

match render_session(&config) {
    Err(e) if e.to_string() == "No session" => eprintln!("start a session first: .session <name>"),
    other => other?,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of sigoden/aichat@82976d349a (2026-09-09). Data as JSON: /api/errors/84af54bd9b93dd24. Report an issue: GitHub.

Appendix: source

Thrown at src/config/mod.rs:1144

        Ok(())
    }

    pub fn session_info(&self) -> Result<String> {
        if let Some(session) = &self.session {
            let render_options = self.render_options()?;
            let mut markdown_render = MarkdownRender::init(render_options)?;
            let agent_info: Option<(String, Vec<String>)> = self.agent.as_ref().map(|agent| {
                let functions = agent
                    .functions()
                    .declarations()
                    .iter()
                    .filter_map(|v| if v.agent { Some(v.name.clone()) } else { None })
                    .collect();
                (agent.name().to_string(), functions)
            });
            session.render(&mut markdown_render, &agent_info)
        } else {
            bail!("No session")
        }
    }

    pub fn exit_session(&mut self) -> Result<()> {
        if let Some(mut session) = self.session.take() {
            let sessions_dir = self.sessions_dir();
            session.exit(&sessions_dir, self.working_mode.is_repl())?;
            self.discontinuous_last_message();
        }
        Ok(())
    }

    pub fn save_session(&mut self, name: Option<&str>) -> Result<()> {
        let session_name = match &self.session {
            Some(session) => match name {
                Some(v) => v.to_string(),
                None => session
                    .autoname()

View on GitHub (pinned to 82976d349a)