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
- List existing conduits (list_all) and reuse the existing one instead of creating a new one.
- If you truly want a fresh conduit, delete the existing one with delete_conduit first, then create.
- 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
- Debounce/disable the create button while a request is in flight.
- Refresh the conduit list after creation so retries see the new row.
- Treat create as idempotent on the (source, target) pair in client logic.
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
- Library with ID '${libraryId}' not found
- This operation requires an active library. Use switchToLibra
- Unexpected response: ${JSON.stringify(response)}
- No library selected. Use client.switchToLibrary() first.
- No library selected. Use client.switchToLibrary() first.
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/c7042578a31d4221.
Report an issue: GitHub.