spacedriveapp/spacedrive · error

This operation requires an active library. Use switchToLibra

Error message

This operation requires an active library. Use switchToLibrary() first.

What it means

Returned by create_conduit when either endpoint entry exists but is not a directory: the code checks `source.kind != 1 || target.kind != 1`, where kind 1 denotes a directory. Sync conduits recursively walk directory trees (see resolver.rs get_entries_recursive), so file endpoints are rejected up front.

Source

Thrown at packages/ts-client/src/client.ts:171

	async getCurrentLibraryInfo() {
		const libraryId = this.getCurrentLibraryId();
		if (!libraryId) return null;

		const libraries = await this.execute<{}, any[]>(
			"query:libraries.list",
			{},
		);
		return libraries.find((lib: any) => lib.id === libraryId) ?? null;
	}

	/**
	 * Require a current library or throw
	 * @internal
	 */
	requireCurrentLibrary(): string {
		const libraryId = this.getCurrentLibraryId();
		if (!libraryId) {
			throw new Error(
				"This operation requires an active library. Use switchToLibrary() first.",
			);
		}
		return libraryId;
	}

	// MARK: - Core Execution Methods

	/**
	 * Execute a wire method with the given input
	 * This is the low-level method used by TanStack Query hooks
	 */
	async execute<I, O>(wireMethod: string, input: I): Promise<O> {
		// Determine if this is a query or action based on wire method prefix
		const isQuery = wireMethod.startsWith("query:");
		const isAction = wireMethod.startsWith("action:");

		if (!isQuery && !isAction) {

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Check both rows: SELECT id, kind, name FROM entry WHERE id IN (<source>, <target>); both must have kind = 1.
  2. If a directory was misclassified, re-index it so kind is corrected.
  3. In the client, filter the picker to directories (kind == 1) before enabling the create button.

Example fix

// before
conduits.create_conduit(file_entry.id, target_dir.id, mode, "*:*".into()).await?;

// after
if file_entry.kind != 1 || target_dir.kind != 1 {
    return Err(anyhow::anyhow!("Pick two directories"));
}
conduits.create_conduit(file_entry.id, target_dir.id, mode, "*:*".into()).await?;
Defensive patterns

Strategy: validation

Validate before calling

// kind == 1 means directory in this schema; check before calling create_conduit.
async fn is_directory_entry(db: &DatabaseConnection, id: i32) -> Result<bool> {
    Ok(entry::Entity::find_by_id(id)
        .one(db)
        .await?
        .map(|e| e.kind == 1)
        .unwrap_or(false))
}

Try / catch

match svc.create_conduit(src, tgt, mode, sched).await {
    Ok(c) => Ok(c),
    Err(e) if e.to_string().contains("must be directories") => {
        Err(anyhow::anyhow!("select folders, not files")) // map to a user-facing message
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Calling create_conduit where either entry is a file (kind 0) or any non-directory kind — e.g. the user picked a file in the picker, or the entry kind was misclassified during indexing.

Common situations: File picker not filtered to folders; drag-and-drop of a file onto a 'sync target' drop zone; entries whose kind field was set incorrectly by a custom import.

Related errors


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