aaif-goose/goose · error · anyhow::Error
Invalid identifier
Error message
Invalid identifier
What it means
anyhow error from the resume branch (crates/goose-cli/src/cli.rs) when the parsed Identifier has none of session_id, name, or path set. Identifier is a clap ArgGroup(required=false, multiple=false); in the resume flow an all-None identifier should normally take the 'most recent session' path, so hitting this branch means an explicitly empty identifier reached code that requires a value — effectively unreachable via the public CLI today.
Source
Thrown at crates/goose-cli/src/cli.rs:435
if let Some(session_id) = id.session_id {
session_id
} else if let Some(name) = id.name {
let sessions = session_manager.list_sessions().await?;
sessions
.into_iter()
.find(|s| s.name == name || s.id == name)
.map(|s| s.id)
.ok_or_else(|| anyhow::anyhow!("No session found with name '{}'", name))?
} else if let Some(path) = id.path {
path.file_stem()
.and_then(|s| s.to_str())
.map(|s| s.to_string())
.ok_or_else(|| {
anyhow::anyhow!("Could not extract session ID from path: {:?}", path)
})?
} else {
return Err(anyhow::anyhow!("Invalid identifier"));
}
} else {
let Some(id) = identifier else {
let session = session_manager
.create_session(
std::env::current_dir()?,
"CLI Session".to_string(),
SessionType::User,
goose_mode,
)
.await?;
return Ok(Some(session.id));
};
if id.session_id.is_some() {
return Err(anyhow::anyhow!("Cannot use --session-id without --resume"));
}
View on GitHub (pinned to 3810898a74)
Solutions
- If calling from code, set at least one field: id.name / id.session_id / id.path
- Prefer letting the no-identifier path run (pass Option::None for the whole identifier) so it resolves the most recent session
- Keep the ArgGroup contract (required=false, multiple=false) intact when editing the CLI
- For scripts, pass an explicit --session-id to make intent unambiguous
Example fix
// before
let id = Identifier::default(); // all None
resolve(id).await?;
// after
let id = Identifier { name: Some("project-x".into()), ..Default::default() };
resolve(id).await?; Defensive patterns
Strategy: validation
Validate before calling
debug_assert!(id.session_id.is_some() || id.name.is_some() || id.path.is_some(), "Identifier must carry a value in the resume per-field branch");
Type guard
fn identifier_has_value(id: &Identifier) -> bool {
id.session_id.is_some() || id.name.is_some() || id.path.is_some()
} Prevention
- Construct Identifier with at least one field in code
- Pass Option::None for the whole identifier when you want 'most recent session' behavior
- Keep the clap ArgGroup contract intact
When it happens
Trigger: Programmatically constructing Identifier::default() (all fields None) and calling the resolution function directly, or a future CLI change that routes an empty identifier into the per-field match instead of the fallback.
Common situations: Unit tests or embedded callers building Identifier by hand; refactors of the clap group that change which arm executes.
Related errors
- No identifier provided
- No session found to resume
- No session found with name '{}'
- Could not extract session ID from path: {:?}
- Cannot use --session-id without --resume
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/7ed7691abdd6ae4d.
Report an issue: GitHub.