spacedriveapp/spacedrive · error

${isQuery ? "Query" : "Action"} failed: ${JSON.stringify(err

Error message

${isQuery ? "Query" : "Action"} failed: ${JSON.stringify(error)}

What it means

Returned by create_conduit when a sync_conduit row with the same (source_entry_id, target_entry_id) pair already exists. The duplicate check queries sync_conduit filtered on both columns before inserting, so re-submitting an identical pair is rejected rather than creating a second conduit.

Source

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

			: {
					Action: {
						method: wireMethod,
						library_id: this.currentLibraryId, // ← Sibling field!
						payload: input,
					},
				};

		const response = await this.transport.sendRequest(request);

		// Handle different response formats
		if ("JsonOk" in response) {
			return response.JsonOk;
		} else if ("json" in response) {
			// Wire protocol uses lowercase "json" for success
			return response.json;
		} else if ("Error" in response || "error" in response) {
			const error = response.Error || response.error;
			throw new Error(
				`${isQuery ? "Query" : "Action"} failed: ${JSON.stringify(error)}`,
			);
		} else {
			throw new Error(`Unexpected response: ${JSON.stringify(response)}`);
		}
	}

	/**
	 * Subscribe to events from the daemon
	 */
	async subscribe(callback?: (event: Event) => void): Promise<() => void> {
		const unlisten = await this.transport.subscribe((event) => {
			if (callback) {
				callback(event);
			}
		});

		return unlisten;

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. List existing conduits (list_all) and reuse the existing one instead of creating a new one.
  2. If you truly want a fresh conduit, delete the existing one with delete_conduit first, then create.
  3. Disable the submit action while the request is in flight to prevent double-submission.

Example fix

// before
let c = svc.create_conduit(src, tgt, mode, sched.clone()).await?;

// after (idempotent create)
let c = match svc.create_conduit(src, tgt, mode.clone(), sched.clone()).await {
    Ok(c) => c,
    Err(e) if e.to_string().contains("already exists") => {
        svc.list_all().await?.into_iter()
            .find(|c| c.source_entry_id == src && c.target_entry_id == tgt)
            .ok_or(e)?
    }
    Err(e) => return Err(e),
};
Defensive patterns

Strategy: validation

Validate before calling

// Idempotent create: check for an existing pair first.
async fn find_existing(
    svc: &ConduitService,
    src: i32,
    tgt: i32,
) -> Result<Option<sync_conduit::Model>> {
    Ok(svc.list_all()
        .await?
        .into_iter()
        .find(|c| c.source_entry_id == src && c.target_entry_id == tgt))
}

Try / catch

match svc.create_conduit(src, tgt, mode, sched).await {
    Ok(c) => Ok(c),
    Err(e) if e.to_string().contains("already exists") => {
        find_existing(svc, src, tgt).await?.ok_or(e) // reuse, don't duplicate
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Calling create_conduit twice with the same source/target entry IDs — double-click on a create button, a client retry after a timeout where the first request actually succeeded, or re-adding a previously created pair.

Common situations: Duplicate form submission without idempotency key; the UI not refreshing its conduit list after creation; retry logic that re-sends a completed request.

Related errors


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