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
- Search for other registry.register calls using the "file_transfer" name and remove/rename the conflicting handler
- Ensure only the canonical FileTransferProtocolHandler is registered under that name
- Clean and rebuild the workspace (cargo clean && cargo build) if crate version skew is suspected
- 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
- Reserve the 'file_transfer' protocol name for the canonical handler; namespace test doubles differently
- Rebuild the whole workspace after core upgrades to avoid type version skew
- Assert the downcast succeeds in a startup smoke test of the registry
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
- File transfer protocol not registered
- Could not resolve destination device slug '{}' to UUID in li
- Networking service not available
- Source must be local path for PUSH operation
- Failed to calculate checksum: {}
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/9deff4589bac2203.
Report an issue: GitHub.