spacedriveapp/spacedrive · error · anyhow::Error
Destination must be local path for PULL operation
Error message
Destination must be local path for PULL operation
What it means
PULL writes incoming bytes to the local filesystem, so destination.as_local_path() must yield a real PathBuf (strategy.rs:430-432). None means the destination SdPath is device-scoped or virtual; there is no local target path at which the downloaded file can be created.
Source
Thrown at core/src/ops/files/copy/strategy.rs:432
}
}
/// Execute a PULL operation (remote -> local)
async fn execute_pull<'a>(
&self,
ctx: &JobContext<'a>,
source: &SdPath,
destination: &SdPath,
verify_checksum: bool,
progress_callback: Option<&ProgressCallback<'a>>,
) -> Result<u64> {
let (source_device_slug, source_path) = source
.as_physical()
.ok_or_else(|| anyhow::anyhow!("Source must be a physical path for PULL operation"))?;
let local_dest_path = destination
.as_local_path()
.ok_or_else(|| anyhow::anyhow!("Destination must be local path for PULL operation"))?;
let library = ctx.library();
let source_device_id = library
.resolve_device_slug(source_device_slug)
.ok_or_else(|| anyhow::anyhow!(
"Could not resolve source device slug '{}' to UUID in library {}. Device may not be registered in this library.",
source_device_slug,
library.id()
))?;
debug!(
"RemoteTransferStrategy PULL: device:{} ({}) -> {}",
source_device_slug,
source_device_id,
local_dest_path.display()
);
info!(View on GitHub (pinned to 6dfeccf211)
Solutions
- Make the destination a local path on the machine running the job
- Run the PULL on the machine that owns the destination location
- Guard destination.as_local_path().is_some() before starting the job
- For both-remote copies, chain two hops (pull here, then push) or execute on one of the endpoints
Example fix
// before
let dest = SdPath::physical("laptop-b", PathBuf::from("photos/a.jpg"));
remote_strategy.execute_pull(ctx, &src, &dest).await?; // "Destination must be local path for PULL operation"
// after
let dest = SdPath::local(PathBuf::from("/home/me/photos/a.jpg"));
remote_strategy.execute_pull(ctx, &src, &dest).await?; Defensive patterns
Strategy: type-guard
Validate before calling
if destination.as_local_path().is_none() {
return Err(anyhow::anyhow!("PULL requires a local destination; got {}", destination));
} Type guard
fn is_local_destination(destination: &SdPath) -> bool {
destination.as_local_path().is_some()
} Prevention
- Materialize destinations to local paths before starting a PULL
- Run the pull job on the machine that owns the destination location
- Reject remote destinations early in the job input validation layer
When it happens
Trigger: Pulling to a destination that lives on another device (device-scoped SdPath); destination built from a virtual library location with no local materialization; both-remote copy attempted from the wrong machine.
Common situations: User drops a file onto a folder that resides on a different device; job executed on a third machine that owns neither endpoint.
Related errors
- Source must be a physical path for PULL operation
- Source must be local path for PUSH operation
- Could not resolve source device slug '{}' to UUID in library
- Could not resolve destination device slug '{}' to UUID in li
- Failed to connect to device: {}
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/88c401ef856e43d7.
Report an issue: GitHub.