spacedriveapp/spacedrive · error · anyhow::Error
File transfer protocol not registered
Error message
File transfer protocol not registered
What it means
PUSH fetches the protocol handler registered under the name "file_transfer" from the NetworkingService's ProtocolRegistry (the canonical handler's protocol_name() returns "file_transfer", core/src/service/network/protocol/file_transfer.rs:1429). None means the registry never received a FileTransferProtocolHandler — networking came up without registering built-in protocols, registration failed, or a custom registry construction omitted it.
Source
Thrown at core/src/ops/files/copy/strategy.rs:366
name: local_path
.file_name()
.unwrap_or_default()
.to_string_lossy()
.to_string(),
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(View on GitHub (pinned to 6dfeccf211)
Solutions
- Check daemon startup logs for protocol registration failures and fix/re-run registration
- Ensure NetworkingService initialization registers built-in protocols before any copy job is dispatched
- If you construct the ProtocolRegistry yourself, register FileTransferProtocolHandler explicitly
- Restart the daemon after fixing init so the registry is repopulated
Example fix
// before
let mut registry = ProtocolRegistry::new(); // no built-ins registered
// after
let mut registry = ProtocolRegistry::new();
registry.register(std::sync::Arc::new(
crate::service::network::protocol::FileTransferProtocolHandler::new(),
)); Defensive patterns
Strategy: validation
Validate before calling
let networking = ctx.networking_service().ok_or_else(|| anyhow::anyhow!("no networking"))?;
let registry = networking.protocol_registry();
if registry.read().await.get_handler("file_transfer").is_none() {
return Err(anyhow::anyhow!("file_transfer protocol not registered; networking started without built-ins"));
} Prevention
- Register built-in protocols during NetworkingService init and assert registration in startup checks
- Log registered protocol names at daemon boot to catch missing handlers early
- In custom/test registries, always add FileTransferProtocolHandler before running copy jobs
When it happens
Trigger: NetworkingService started in a mode that skips built-in protocol registration; init-order bug where the copy job runs before registration completes; test or embedded setup constructing a bare ProtocolRegistry without the file-transfer handler.
Common situations: Custom daemon builds with protocol registration toggled off; startup error during registration swallowed earlier; refactoring that moved registration out of the boot path.
Related errors
- Networking service not available
- Invalid file transfer protocol handler
- Unknown config key: {}
- Could not resolve destination device slug '{}' to UUID in li
- Source must be local path for PUSH operation
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/fe48a59a531b2d6b.
Report an issue: GitHub.