{"record":{"id":"9deff4589bac2203","repo":"spacedriveapp/spacedrive","slug":"invalid-file-transfer-protocol-handler","errorCode":null,"errorMessage":"Invalid file transfer protocol handler","messagePattern":"Invalid file transfer protocol handler","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"core/src/ops/files/copy/strategy.rs","lineNumber":371,"sourceCode":"\t\t\tsize: file_size,\n\t\t\tmodified: metadata.modified().ok(),\n\t\t\tis_directory: metadata.is_dir(),\n\t\t\tchecksum,\n\t\t\tmime_type: None,\n\t\t};\n\n\t\tlet networking_guard = &*networking;\n\t\tlet protocol_registry = networking_guard.protocol_registry();\n\t\tlet registry_guard = protocol_registry.read().await;\n\n\t\tlet file_transfer_handler = registry_guard\n\t\t\t.get_handler(\"file_transfer\")\n\t\t\t.ok_or_else(|| anyhow::anyhow!(\"File transfer protocol not registered\"))?;\n\n\t\tlet file_transfer_protocol = file_transfer_handler\n\t\t\t.as_any()\n\t\t\t.downcast_ref::<crate::service::network::protocol::FileTransferProtocolHandler>()\n\t\t\t.ok_or_else(|| anyhow::anyhow!(\"Invalid file transfer protocol handler\"))?;\n\n\t\tlet transfer_id = file_transfer_protocol\n\t\t\t.initiate_transfer(\n\t\t\t\tdest_device_id,\n\t\t\t\tlocal_path.to_path_buf(),\n\t\t\t\tcrate::service::network::protocol::TransferMode::TrustedCopy,\n\t\t\t)\n\t\t\t.await?;\n\n\t\tdebug!(\"PUSH transfer initiated with ID: {}\", transfer_id);\n\t\tctx.log(format!(\"PUSH transfer initiated with ID: {}\", transfer_id));\n\n\t\tlet result = stream_file_data(\n\t\t\tlocal_path,\n\t\t\ttransfer_id,\n\t\t\tfile_transfer_protocol,\n\t\t\tfile_size,\n\t\t\tdest_device_id,","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/core/src/ops/files/copy/strategy.rs#L353-L389","documentation":"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.","triggerScenarios":"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.","commonSituations":"Test doubles registered with the production protocol name; monorepo version skew between daemon binary and core crate after a partial rebuild.","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"],"exampleFix":"// before\nregistry.register(std::sync::Arc::new(MyMockHandler::new())); // protocol_name() == \"file_transfer\"\n\n// after\nregistry.register(std::sync::Arc::new(\n    crate::service::network::protocol::FileTransferProtocolHandler::new(),\n));","handlingStrategy":"validation","validationCode":"let handler = registry.read().await.get_handler(\"file_transfer\")\n    .ok_or_else(|| anyhow::anyhow!(\"file_transfer not registered\"))?;\nif handler.as_any().downcast_ref::<FileTransferProtocolHandler>().is_none() {\n    return Err(anyhow::anyhow!(\"conflicting handler registered under 'file_transfer'\"));\n}","typeGuard":"fn is_file_transfer_handler(h: &dyn ProtocolHandler) -> bool {\n    h.as_any().downcast_ref::<crate::service::network::protocol::FileTransferProtocolHandler>().is_some()\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["rust","spacedrive","push","downcast","protocol-registry","version-skew"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}