{"record":{"id":"03ce34c7fb482936","repo":"spacedriveapp/spacedrive","slug":"usespacedriveclient-must-be-used-within-spacedrive","errorCode":null,"errorMessage":"useSpacedriveClient must be used within SpacedriveProvider","messagePattern":"useSpacedriveClient must be used within SpacedriveProvider","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/ts-client/src/hooks/useClient.tsx","lineNumber":48,"sourceCode":"export function SpacedriveProvider({ client, children }: SpacedriveProviderProps) {\n\treturn (\n\t\t<QueryClientProvider client={queryClient}>\n\t\t\t<SpacedriveClientContext.Provider value={client}>\n\t\t\t\t{children}\n\t\t\t</SpacedriveClientContext.Provider>\n\t\t</QueryClientProvider>\n\t);\n}\n\n/**\n * Hook to access the Spacedrive client\n * Must be used within a SpacedriveProvider\n */\nexport function useSpacedriveClient(): SpacedriveClient {\n\tconst client = useContext(SpacedriveClientContext);\n\n\tif (!client) {\n\t\tthrow new Error(\"useSpacedriveClient must be used within SpacedriveProvider\");\n\t}\n\n\treturn client;\n}\n\n// Also export for direct use\nexport { useClient };\nfunction useClient() {\n\treturn useSpacedriveClient();\n}\n","sourceCodeStart":30,"sourceCodeEnd":59,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/packages/ts-client/src/hooks/useClient.tsx#L30-L59","documentation":"Returned inside sync_now's copy-job dispatch branch when the SdPath list built from operations.to_copy is empty — the code takes source_paths.first() to derive the MVP destination and errors when there is nothing to copy. Because the branch was entered expecting copies, this indicates an empty/degenerate operation set rather than a user-input problem.","triggerScenarios":"A sync calculation that produced zero copy operations while still entering the dispatch branch — e.g. trees already in sync (only deletes or no-ops), or a race where the operations were computed against stale state. The comment marks it as MVP behavior: destination is 'first entry's parent', which is undefined for an empty list.","commonSituations":"Repeated sync_now calls on an already-converged conduit; deletion-only diffs; edge case in operation calculation returning an empty to_copy alongside a non-empty aggregate copy_count path.","solutions":["Treat it as a no-op: if nothing changed, skip the copy-job dispatch instead of surfacing an error (the operations already told you to_copy is empty).","Check the computed operation counts (copy_count/delete_count logged by sync_now) to confirm the diff is genuinely empty.","File/track a code fix: guard `if source_paths.is_empty() { return Ok(None) }` before building FileCopyJob, since erroring on an empty batch is not actionable."],"exampleFix":"// before\nlet destination = if let Some(first) = source_paths.first() {\n    first.clone()\n} else {\n    return Err(anyhow::anyhow!(\"No paths to copy\"));\n};\n\n// after (empty diff is a no-op, not an error)\nlet Some(first) = source_paths.first() else {\n    return Ok(None); // nothing to copy\n};\nlet destination = first.clone();","handlingStrategy":"fallback","validationCode":"// Skip dispatch when the diff has no copies.\nif operations.source_to_target.to_copy.is_empty()\n    && operations.target_to_source.as_ref().map_or(true, |o| o.to_copy.is_empty())\n{\n    return Ok(None); // nothing to copy, nothing to dispatch\n}","typeGuard":null,"tryCatchPattern":"match dispatch_copy_job(&operations).await {\n    Ok(h) => Ok(h),\n    Err(e) if e.to_string() == \"No paths to copy\" => Ok(None), // empty diff = no-op\n    Err(e) => Err(e),\n}","preventionTips":["Check to_copy counts before entering the copy-dispatch branch.","Treat already-in-sync conduits as success (no-op) in orchestration code.","Track the MVP destination limitation ('first entry's parent') — verify it matches intended target semantics before relying on it."],"tags":["rust","file-sync","edge-case","mvp-limitation"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}