Hmbown/CodeWhale · error

Session id cannot be empty

Error message

Session id cannot be empty

What it means

validated_session_id rejects a session id that is empty or whitespace-only before it is used to build file paths, returning InvalidInput with 'Session id cannot be empty'. The function both trims the id and validates it, so passing raw unvalidated input here trips this first check. It guards against creating path-less or unnamed session artifacts.

Solutions

  1. Provide a non-empty session id before calling session-manager APIs
  2. Validate/default the id at construction time of SavedSession metadata
  3. Check where the id originates (env var, CLI flag, config) and add an earlier required-field check

Example fix

// before
manager.checkpoint_path(&opts.session_id)?;
// after
let id = opts.session_id.clone().filter(|s| !s.trim().is_empty()).ok_or_else(|| anyhow!("--session-id is required"))?;
manager.checkpoint_path(&id)?;
Defensive patterns

Strategy: validation

Validate before calling

if opts.session_id.trim().is_empty() { return Err(anyhow!("--session-id is required")); }

Type guard

fn valid_session_id(id: &str) -> bool { !id.trim().is_empty() }

Try / catch

match manager.checkpoint_path(&id) {
    Ok(p) => use(p),
    Err(e) if e.kind() == io::ErrorKind::InvalidInput && e.to_string().contains("empty") => prompt_user_for_session_id(),
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling validated_session_id("") or a whitespace-only string; passing an uninitialized/None-defaulted id field from session metadata or a CLI flag.

Common situations: A session id env var or CLI option unset; session metadata JSON missing the id field and defaulting to empty; constructing a session programmatically without assigning an id.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/ee80ee660427385e. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/session_manager.rs:1268

        if !durable.is_empty() {
            session.approval_receipts = durable;
        }
        ApprovalReplay::from_receipts(&session.approval_receipts)
            .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
        Ok(())
    }

    /// Reconstruct completed approvals and interrupted unmatched asks for one
    /// session without consulting the model transcript.
    #[cfg_attr(not(test), expect(dead_code))]
    pub(crate) fn replay_approvals(&self, session_id: &str) -> io::Result<ApprovalReplay> {
        self.approval_receipt_store().replay(session_id)
    }

    fn validated_session_id<'a>(&self, id: &'a str) -> std::io::Result<&'a str> {
        let trimmed = id.trim();
        if trimmed.is_empty() {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                "Session id cannot be empty",
            ));
        }
        if !trimmed
            .chars()
            .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
        {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                format!("Invalid session id '{id}'"),
            ));
        }
        if trimmed == SESSION_BOOT_OWNERS_STEM {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                format!("Session id '{trimmed}' collides with a reserved sessions file"),
            ));

View on GitHub (pinned to 73e0f67d83)