{"record":{"id":"2e7c4ea73d718c70","repo":"spacedriveapp/spacedrive","slug":"source-must-be-local-path-for-push-operation","errorCode":null,"errorMessage":"Source must be local path for PUSH operation","messagePattern":"Source must be local path for PUSH operation","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"core/src/ops/files/copy/strategy.rs","lineNumber":321,"sourceCode":"\t\t\t.resolve_device_slug(dest_device_slug)\n\t\t\t.ok_or_else(|| anyhow::anyhow!(\n\t\t\t\t\"Could not resolve destination device slug '{}' to UUID in library {}. Device may not be registered in this library.\",\n\t\t\t\tdest_device_slug,\n\t\t\t\tlibrary.id()\n\t\t\t))?;\n\n\t\tdebug!(\n\t\t\t\"RemoteTransferStrategy PUSH: {} -> device:{} ({})\",\n\t\t\tsource, dest_device_slug, dest_device_id\n\t\t);\n\n\t\tlet networking = ctx\n\t\t\t.networking_service()\n\t\t\t.ok_or_else(|| anyhow::anyhow!(\"Networking service not available\"))?;\n\n\t\tlet local_path = source\n\t\t\t.as_local_path()\n\t\t\t.ok_or_else(|| anyhow::anyhow!(\"Source must be local path for PUSH operation\"))?;\n\n\t\tlet metadata = tokio::fs::metadata(local_path).await?;\n\t\tlet file_size = metadata.len();\n\n\t\tlet checksum = calculate_file_checksum(local_path)\n\t\t\t.await\n\t\t\t.map(Some)\n\t\t\t.map_err(|e| anyhow::anyhow!(\"Failed to calculate checksum: {}\", e))?;\n\n\t\tinfo!(\n\t\t\t\"Initiating PUSH transfer: {} ({} bytes) -> device:{} ({})\",\n\t\t\tlocal_path.display(),\n\t\t\tfile_size,\n\t\t\tdest_device_slug,\n\t\t\tdest_device_id\n\t\t);\n\n\t\tctx.log(format!(","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/core/src/ops/files/copy/strategy.rs#L303-L339","documentation":"PUSH streams bytes from this machine to the peer, so the source must resolve to a local filesystem path. source.as_local_path() returns None when the SdPath is a device-scoped (physical) or otherwise non-local variant, leaving nothing local to read and stream (strategy.rs:319-321). Note the direction chooser defaults both-remote cases to Push (strategy.rs:280-283), which then fails here.","triggerScenarios":"PUSH invoked with a source bound to a remote device slug; both source and destination remote so determine_direction falls through to Push over an unsupported case; source SdPath constructed via a physical/virtual form instead of a local path.","commonSituations":"Custom job code calling RemoteTransferStrategy directly; both-remote copy attempted from a third machine; source built with SdPath::physical while the file is actually local.","solutions":["Make the source a local path (download/materialize it first) before a PUSH copy","If the file lives on the remote device, run the copy on that device or use PULL from the destination device","Fix direction selection so both-remote raises 'not supported' instead of defaulting to Push","Validate source.as_local_path().is_some() before dispatching to the remote strategy"],"exampleFix":"// before\n// source = SdPath::physical(\"nas\", \"/data/a.jpg\")\nremote_strategy.execute_push(ctx, &source, &dest).await?; // \"Source must be local path for PUSH operation\"\n\n// after\nmatch source.as_local_path() {\n    Some(_local) => remote_strategy.execute_push(ctx, &source, &dest).await,\n    None => Err(anyhow::anyhow!(\"source {} is remote; PULL it from the owning device instead\", source)),\n}","handlingStrategy":"type-guard","validationCode":"if source.as_local_path().is_none() {\n    return Err(anyhow::anyhow!(\"PUSH requires a local source; got {}\", source));\n}","typeGuard":"fn is_local_source(source: &SdPath) -> bool {\n    source.as_local_path().is_some()\n}","tryCatchPattern":null,"preventionTips":["Narrow on SdPath variant (as_local_path/as_physical) before choosing PUSH vs PULL","Reject both-remote copies explicitly instead of relying on the Push default","Build source paths with SdPath::local when the file is on this machine"],"tags":["rust","spacedrive","push","sd-path","cross-device","copy"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}