astrid-runtime/astrid · error

Invalid session ID (must be a UUID): {id}

Error message

Invalid session ID (must be a UUID): {id}

What it means

delete_session validates the session id as a UUID before touching the filesystem, specifically to prevent path traversal such as '../../config'. If uuid::Uuid::parse_str rejects the id, this error is returned and no directory is ever joined or removed.

Source

Thrown at crates/astrid-cli/src/commands/sessions.rs:56

    sessions.sort_by_key(|s| std::cmp::Reverse(s.1));

    println!("{}", "Active Sessions:".bold());
    for (id, modified) in sessions {
        let time = chrono::DateTime::<chrono::Local>::from(modified)
            .format("%Y-%m-%d %H:%M:%S")
            .to_string();
        println!("  {} ({})", Theme::session_id(&id), Theme::dimmed(&time));
    }

    Ok(())
}

/// Delete a session by UUID.
pub(crate) fn delete_session(id: &str) -> Result<()> {
    // Validate as UUID to prevent path traversal (e.g. "../../config")
    uuid::Uuid::parse_str(id)
        .map_err(|_| anyhow::anyhow!("Invalid session ID (must be a UUID): {id}"))?;
    let home = AstridHome::resolve().context("Failed to resolve Astrid home directory")?;
    let session_dir = home.run_dir().join(id);

    if !session_dir.exists() {
        anyhow::bail!("Session not found: {id}");
    }

    fs::remove_dir_all(&session_dir)?;
    println!("{}", Theme::success(&format!("Deleted session {id}")));
    Ok(())
}

/// Show information about a session by UUID.
pub(crate) fn session_info(id: &str) -> Result<()> {
    uuid::Uuid::parse_str(id)
        .map_err(|_| anyhow::anyhow!("Invalid session ID (must be a UUID): {id}"))?;
    let home = AstridHome::resolve().context("Failed to resolve Astrid home directory")?;
    let session_dir = home.run_dir().join(id);

View on GitHub (pinned to affd8760f4)

Solutions

  1. Run the sessions list command and copy the exact UUID for the session
  2. Trim whitespace/quotes and use only the raw UUID (hyphenated form works)
  3. Verify the id is a valid UUID (e.g. uuidgen or an online validator) before retrying
  4. If the ID came from a script, quote and parse it properly to avoid mangling

Example fix

// before
astrid sessions delete ../../config
// after
astrid sessions delete 3f2b8c1a-9d4e-4f01-b2a3-5c6d7e8f9012
Defensive patterns

Strategy: validation

Validate before calling

fn is_uuid(s: &str) -> bool { uuid::Uuid::parse_str(s).is_ok() }
if !is_uuid(id) { eprintln!("{id} is not a UUID; copy the id from `astrid sessions list`"); return; }

Type guard

fn is_uuid(s: &str) -> bool { uuid::Uuid::parse_str(s).is_ok() }

Try / catch

match delete_session(id) {
    Ok(()) => println!("deleted"),
    Err(e) if e.to_string().starts_with("Invalid session ID") => eprintln!("Pass the full UUID shown by `astrid sessions list`"),
    Err(e) => eprintln!("delete failed: {e}"),
}

Prevention

When it happens

Trigger: Calling delete_session with an id string that is not a canonical UUID — arbitrary names, relative paths, truncated IDs, extra whitespace, or braces-wrapped UUIDs.

Common situations: Passing a session name/short label instead of the UUID from `astrid sessions list`; copy-paste errors including quotes or path characters; scripting with stale or hand-edited IDs.

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 astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/9e5efa08b7128c9b. Report an issue: GitHub.