astrid-runtime/astrid · error
WinFsp callback probe protocol mismatch
Error message
WinFsp callback probe protocol mismatch
What it means
probe_callback requires every StorageFilesystemResponseV2 to carry protocol_version == STORAGE_FILESYSTEM_PROTOCOL_V2. A well-formed but differently-versioned response is rejected, protecting the daemon from talking to an incompatible callback implementation.
Solutions
- Rebuild/upgrade the callback responder so its protocol_version equals STORAGE_FILESYSTEM_PROTOCOL_V2.
- Align crate versions of the daemon and callback library (same workspace revision) and re-deploy both.
- Confirm the process answering on callback_path is actually the expected astrid callback, not another service.
- If you intentionally bumped the protocol, update STORAGE_FILESYSTEM_PROTOCOL_V2 and the wire format on both sides together.
Example fix
// before (responder)
StorageFilesystemResponseV2 { protocol_version: STORAGE_FILESYSTEM_PROTOCOL_V1, .. }
// after
StorageFilesystemResponseV2 { protocol_version: STORAGE_FILESYSTEM_PROTOCOL_V2, .. } Defensive patterns
Strategy: type-guard
Validate before calling
fn response_version_ok(resp: &StorageFilesystemResponseV2) -> bool {
resp.protocol_version == STORAGE_FILESYSTEM_PROTOCOL_V2
} Type guard
fn is_v2_response(resp: &StorageFilesystemResponseV2) -> bool {
resp.protocol_version == STORAGE_FILESYSTEM_PROTOCOL_V2
} Try / catch
match probe_callback(&launch, &request).await {
Err(e) if e.to_string().contains("protocol mismatch") => {
// pin both sides to the same crate version, then retry
Err(e)
},
other => other,
} Prevention
- Keep the daemon and callback library on identical crate versions in your lockfile.
- Guard the responder against accepting requests with an unknown protocol version.
- Add a cross-version CI test so protocol bumps fail loudly.
When it happens
Trigger: run_private_service -> probe_callback when the responder answers the probe with a serialized StorageFilesystemResponseV2 whose protocol_version field differs from STORAGE_FILESYSTEM_PROTOCOL_V2 (older v1 responder, or newer protocol bump).
Common situations: Mixed-version deployment: daemon built against protocol v2 but callback library still v1; after upgrading the storage crate one side wasn't rebuilt; a different service answering on callback_path with its own protocol constant.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- kernel returned an unexpected storage lifecycle response
- MCP gateway returned an unbound control acknowledgement
- protocol mismatch: expected , received
- unsupported provider protocol
- unsupported storage filesystem protocol
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/1a0699415bfde94e.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-storage-provider-winfsp/src/win.rs:366
},
};
let bytes = serde_json::to_vec(&request).context("encode WinFsp callback probe")?;
let length = u32::try_from(bytes.len()).context("WinFsp callback probe is too large")?;
stream.write_all(&length.to_be_bytes()).await?;
stream.write_all(&bytes).await?;
stream.flush().await?;
let mut response_length = [0_u8; 4];
stream.read_exact(&mut response_length).await?;
let length = u32::from_be_bytes(response_length) as usize;
if length == 0 || length > SERVICE_MAX_CALLBACK_BYTES {
bail!("WinFsp callback response exceeds limit");
}
let mut response_bytes = vec![0_u8; length];
stream.read_exact(&mut response_bytes).await?;
let response: StorageFilesystemResponseV2 =
serde_json::from_slice(&response_bytes).context("decode WinFsp callback probe")?;
if response.protocol_version != STORAGE_FILESYSTEM_PROTOCOL_V2 {
bail!("WinFsp callback probe protocol mismatch");
}
if response.request_id != request.request_id {
bail!("WinFsp callback probe correlation mismatch");
}
match response.outcome {
StorageFilesystemOutcomeV2::Success(_) => Ok(()),
StorageFilesystemOutcomeV2::Failure(StorageFilesystemFailureV1 { code, message }) => {
bail!("WinFsp callback probe failed [{code}]: {message}")
},
}
}
async fn private_service_loop(
filesystem: FileSystem,
listener: local_transport::LocalListener,
launch: &StorageProviderServiceLaunchV1,
) -> Result<()> {
let mut filesystem = Some(filesystem);View on GitHub (pinned to affd8760f4)