spacedriveapp/spacedrive · error · anyhow::Error

Invalid file transfer protocol handler

Error message

Invalid file transfer protocol handler

What it means

The object stored under "file_transfer" must downcast to crate::service::network::protocol::FileTransferProtocolHandler (strategy.rs:368-371). The name resolved, but the concrete type differs — something else registered under the same protocol name (custom handler, mock, or a different build of the type), so calling initiate_transfer on it would be unsound and the copy aborts.

Source

Thrown at core/src/ops/files/copy/strategy.rs:371

			size: file_size,
			modified: metadata.modified().ok(),
			is_directory: metadata.is_dir(),
			checksum,
			mime_type: None,
		};

		let networking_guard = &*networking;
		let protocol_registry = networking_guard.protocol_registry();
		let registry_guard = protocol_registry.read().await;

		let file_transfer_handler = registry_guard
			.get_handler("file_transfer")
			.ok_or_else(|| anyhow::anyhow!("File transfer protocol not registered"))?;

		let file_transfer_protocol = file_transfer_handler
			.as_any()
			.downcast_ref::<crate::service::network::protocol::FileTransferProtocolHandler>()
			.ok_or_else(|| anyhow::anyhow!("Invalid file transfer protocol handler"))?;

		let transfer_id = file_transfer_protocol
			.initiate_transfer(
				dest_device_id,
				local_path.to_path_buf(),
				crate::service::network::protocol::TransferMode::TrustedCopy,
			)
			.await?;

		debug!("PUSH transfer initiated with ID: {}", transfer_id);
		ctx.log(format!("PUSH transfer initiated with ID: {}", transfer_id));

		let result = stream_file_data(
			local_path,
			transfer_id,
			file_transfer_protocol,
			file_size,
			dest_device_id,

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Search for other registry.register calls using the "file_transfer" name and remove/rename the conflicting handler
  2. Ensure only the canonical FileTransferProtocolHandler is registered under that name
  3. Clean and rebuild the workspace (cargo clean && cargo build) if crate version skew is suspected
  4. Restart the daemon so the corrected registry takes effect

Example fix

// before
registry.register(std::sync::Arc::new(MyMockHandler::new())); // protocol_name() == "file_transfer"

// after
registry.register(std::sync::Arc::new(
    crate::service::network::protocol::FileTransferProtocolHandler::new(),
));
Defensive patterns

Strategy: validation

Validate before calling

let handler = registry.read().await.get_handler("file_transfer")
    .ok_or_else(|| anyhow::anyhow!("file_transfer not registered"))?;
if handler.as_any().downcast_ref::<FileTransferProtocolHandler>().is_none() {
    return Err(anyhow::anyhow!("conflicting handler registered under 'file_transfer'"));
}

Type guard

fn is_file_transfer_handler(h: &dyn ProtocolHandler) -> bool {
    h.as_any().downcast_ref::<crate::service::network::protocol::FileTransferProtocolHandler>().is_some()
}

Prevention

When it happens

Trigger: A custom or mock handler registered under the "file_transfer" name; two versions of the networking/core crates linked so the registered type and the referenced type differ; refactored handler that kept the name but changed type.

Common situations: Test doubles registered with the production protocol name; monorepo version skew between daemon binary and core crate after a partial rebuild.

Related errors


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