spacedriveapp/spacedrive · error · anyhow::Error
No library selected. Use 'sd library switch' to select a…
Error message
No library selected. Use 'sd library switch' to select a library first.
What it means
Thrown by 'sd sync metrics' (single-query mode) when ctx.library_id is None. Sync metrics (GetSyncMetricsInput) are queried per-library, and the CLI Context had no current library in its config, so the command refuses before calling the daemon. The message directs you to 'sd library switch'.
Solutions
- Run 'sd library switch <library-id>' (find IDs via 'sd library list')
- Create a library if the daemon has none: 'sd library create'
- Re-run 'sd sync metrics'
Defensive patterns
Strategy: validation
Validate before calling
let Some(library_id) = ctx.get_current_library_id() else {
eprintln!("No current library. Run 'sd library list', then 'sd library switch <id>'.");
return Ok(());
}; Type guard
fn has_current_library(ctx: &Context) -> bool {
ctx.library_id.is_some()
} Prevention
- Run 'sd library switch' at the start of any session using sync metrics
- Check 'sd config get current_library_id' when in doubt
- Handle a None library id once in a shared helper rather than per command
When it happens
Trigger: Running 'sd sync metrics' (with any --since/--peer/model filters) on a CLI that has no current_library_id in its config.
Common situations: First use on a new machine; library was deleted leaving the config pointing nowhere (context startup clears it); automated scripts that never switch libraries.
Related errors
- Library merging is not yet implemented
- No libraries found on remote device. Use 'Share my library'…
- No library selected
- No library selected. Run 'sd library list' to see available…
- Invalid duration format
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/898360f28d91f375.
Report an issue: GitHub.
Appendix: source
Thrown at apps/cli/src/domains/sync/mod.rs:69
if args.watch {
run_watch_mode(ctx, since, peer_id, &args).await?;
} else {
run_single_query(ctx, since, peer_id, &args).await?;
}
}
}
Ok(())
}
async fn run_single_query(
ctx: &Context,
since: Option<DateTime<Utc>>,
peer_id: Option<uuid::Uuid>,
args: &SyncMetricsArgs,
) -> Result<()> {
// Check if we have a library ID
let library_id = ctx.library_id.ok_or_else(|| {
anyhow::anyhow!("No library selected. Use 'sd library switch' to select a library first.")
})?;
// Call the sync metrics API
let input = GetSyncMetricsInput {
since,
peer_id,
model_type: args.model.clone(),
state_only: if args.state { Some(true) } else { None },
operations_only: if args.operations { Some(true) } else { None },
errors_only: if args.errors { Some(true) } else { None },
};
let json_response = ctx.core.query(&input, Some(library_id)).await?;
let output: sd_core::ops::sync::get_metrics::GetSyncMetricsOutput =
serde_json::from_value(json_response)?;
if args.json {
println!("{}", serde_json::to_string_pretty(&output.metrics)?);View on GitHub (pinned to 6dfeccf211)