Hmbown/CodeWhale · error

Session id ' ' collides with a reserved sessions file

Error message

Session id '{id}' collides with a reserved sessions file

What it means

After character validation, validated_session_id rejects an id equal to SESSION_BOOT_OWNERS_STEM, the reserved stem of the sessions boot-owners file, with 'Session id ... collides with a reserved sessions file'. Preventing this collision stops a per-session file from overwriting the manager's own bookkeeping file in the sessions directory.

Solutions

  1. Choose a different session id that does not match the reserved boot-owners stem
  2. Rename the imported/foreign session before loading it into the manager
  3. If the id must be preserved, prefix or suffix it (e.g. 'my-') so it no longer equals the reserved stem

Example fix

// before
manager.resume(&"boot-owners")?; // reserved stem
// after
manager.resume(&"boot-owners-backup")?;
Defensive patterns

Strategy: validation

Validate before calling

if id.trim() == SESSION_BOOT_OWNERS_STEM { return Err(anyhow!("id is reserved")); }

Try / catch

match manager.checkpoint_path(&id) {
    Ok(p) => use(p),
    Err(e) if e.to_string().contains("reserved sessions file") => eprintln!("'{}' is reserved; pick another name", id),
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling validated_session_id with an id that trims exactly to the reserved boot-owners stem constant.

Common situations: A user names a session after the reserved file stem; a foreign /load file or imported session carries that id; tests or scripts hardcode the reserved name as a fixture id.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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

Appendix: source

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

    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"),
            ));
        }
        Ok(trimmed)
    }

    fn validated_session_path(&self, id: &str) -> std::io::Result<PathBuf> {
        let trimmed = self.validated_session_id(id)?;
        Ok(self.sessions_dir.join(format!("{trimmed}.json")))
    }

    fn checkpoints_dir(&self) -> PathBuf {
        self.sessions_dir.join("checkpoints")
    }

    fn session_goals_dir(&self) -> PathBuf {
        self.sessions_dir.join(SESSION_GOALS_DIR)

View on GitHub (pinned to 73e0f67d83)