spacedriveapp/spacedrive · error · anyhow::Error

No library selected. Use 'sd library switch' to select a lib

Error message

No library selected. Use 'sd library switch' to select a library.

What it means

Returned by SyncResolver::calculate_operations when the entry row for conduit.target_entry_id is missing. It is checked right after the source root lookup, so hitting it means the source endpoint was valid but the target side dangles. The resolver needs both roots to recursively load and diff the two trees.

Source

Thrown at apps/cli/src/context.rs:116

	/// Get current library info
	pub async fn get_current_library_info(
		&self,
	) -> Result<Option<sd_core::ops::libraries::info::output::LibraryInfoOutput>> {
		if let Some(_library_id) = self.library_id {
			let input = sd_core::ops::libraries::info::query::LibraryInfoQueryInput {};
			let info: sd_core::ops::libraries::info::output::LibraryInfoOutput =
				execute_query!(self, input);
			Ok(Some(info))
		} else {
			Ok(None)
		}
	}

	/// Require a current library (error if none set)
	pub fn require_current_library(&self) -> Result<Uuid> {
		self.library_id.ok_or_else(|| {
			anyhow::anyhow!("No library selected. Use 'sd library switch' to select a library.")
		})
	}

	/// Get current library ID or throw error
	pub fn get_current_library_id_or_throw(&self) -> Result<Uuid> {
		self.require_current_library()
	}

	/// Create a new library and optionally switch to it
	pub async fn create_and_switch_to_library(
		&mut self,
		name: String,
		path: PathBuf,
		set_as_current: bool,
	) -> Result<Uuid> {
		let input = sd_core::ops::libraries::create::input::LibraryCreateInput {
			name: name.clone(),
			path: Some(path),

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Check: SELECT target_entry_id FROM sync_conduit WHERE id = <id>; verify that entry id exists.
  2. Re-index the target location to recreate the entry, then repoint or recreate the conduit.
  3. Otherwise remove the conduit with delete_conduit.
Defensive patterns

Strategy: validation

Validate before calling

async fn target_root_exists(db: &DatabaseConnection, c: &sync_conduit::Model) -> Result<bool> {
    Ok(entry::Entity::find_by_id(c.target_entry_id)
        .one(db)
        .await?
        .is_some())
}

Try / catch

match svc.sync_now(conduit_id).await {
    Ok(h) => Ok(h),
    Err(e) if e.to_string().contains("Target entry not found") => {
        prompt_recreate_target(conduit_id); // or delete_conduit
        Err(e)
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: sync_now / calculate_operations on a conduit whose target directory entry was deleted after the conduit was created — target folder removed and reindexed, entry row pruned, or DB restored inconsistently.

Common situations: Target folder on an external/unmounted volume whose entries were pruned; user deleted the target inside the app without cleaning up conduits; backup/restore asymmetry between entry and sync_conduit tables.

Related errors


AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16). Data as JSON: /api/errors/ab49db9e9ea9b094. Report an issue: GitHub.