{"record":{"id":"9e5efa08b7128c9b","repo":"astrid-runtime/astrid","slug":"invalid-session-id-must-be-a-uuid-id","errorCode":null,"errorMessage":"Invalid session ID (must be a UUID): {id}","messagePattern":"Invalid session ID \\(must be a UUID\\): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/sessions.rs","lineNumber":56,"sourceCode":"\n    sessions.sort_by_key(|s| std::cmp::Reverse(s.1));\n\n    println!(\"{}\", \"Active Sessions:\".bold());\n    for (id, modified) in sessions {\n        let time = chrono::DateTime::<chrono::Local>::from(modified)\n            .format(\"%Y-%m-%d %H:%M:%S\")\n            .to_string();\n        println!(\"  {} ({})\", Theme::session_id(&id), Theme::dimmed(&time));\n    }\n\n    Ok(())\n}\n\n/// Delete a session by UUID.\npub(crate) fn delete_session(id: &str) -> Result<()> {\n    // Validate as UUID to prevent path traversal (e.g. \"../../config\")\n    uuid::Uuid::parse_str(id)\n        .map_err(|_| anyhow::anyhow!(\"Invalid session ID (must be a UUID): {id}\"))?;\n    let home = AstridHome::resolve().context(\"Failed to resolve Astrid home directory\")?;\n    let session_dir = home.run_dir().join(id);\n\n    if !session_dir.exists() {\n        anyhow::bail!(\"Session not found: {id}\");\n    }\n\n    fs::remove_dir_all(&session_dir)?;\n    println!(\"{}\", Theme::success(&format!(\"Deleted session {id}\")));\n    Ok(())\n}\n\n/// Show information about a session by UUID.\npub(crate) fn session_info(id: &str) -> Result<()> {\n    uuid::Uuid::parse_str(id)\n        .map_err(|_| anyhow::anyhow!(\"Invalid session ID (must be a UUID): {id}\"))?;\n    let home = AstridHome::resolve().context(\"Failed to resolve Astrid home directory\")?;\n    let session_dir = home.run_dir().join(id);","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/sessions.rs#L38-L74","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run the sessions list command and copy the exact UUID for the session","Trim whitespace/quotes and use only the raw UUID (hyphenated form works)","Verify the id is a valid UUID (e.g. uuidgen or an online validator) before retrying","If the ID came from a script, quote and parse it properly to avoid mangling"],"exampleFix":"// before\nastrid sessions delete ../../config\n// after\nastrid sessions delete 3f2b8c1a-9d4e-4f01-b2a3-5c6d7e8f9012","handlingStrategy":"validation","validationCode":"fn is_uuid(s: &str) -> bool { uuid::Uuid::parse_str(s).is_ok() }\nif !is_uuid(id) { eprintln!(\"{id} is not a UUID; copy the id from `astrid sessions list`\"); return; }","typeGuard":"fn is_uuid(s: &str) -> bool { uuid::Uuid::parse_str(s).is_ok() }","tryCatchPattern":"match delete_session(id) {\n    Ok(()) => println!(\"deleted\"),\n    Err(e) if e.to_string().starts_with(\"Invalid session ID\") => eprintln!(\"Pass the full UUID shown by `astrid sessions list`\"),\n    Err(e) => eprintln!(\"delete failed: {e}\"),\n}","preventionTips":["Always copy session IDs verbatim from the sessions list output","Trim whitespace/quotes when passing IDs from scripts","Validate UUID format client-side before invoking CLI commands","Never pass paths or labels where a UUID is expected"],"tags":["cli","validation","uuid","path-traversal"],"backgroundTag":"invalid-identifier-format","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}