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

  1. Make the destination a local path on the machine running the job
  2. Run the PULL on the machine that owns the destination location
  3. Guard destination.as_local_path().is_some() before starting the job
  4. 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

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


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