{"record":{"id":"70d651afc346b104","repo":"astrid-runtime/astrid","slug":"winfsp-callback-probe-correlation-mismatch","errorCode":null,"errorMessage":"WinFsp callback probe correlation mismatch","messagePattern":"WinFsp callback probe correlation mismatch","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-winfsp/src/win.rs","lineNumber":369,"sourceCode":"    let length = u32::try_from(bytes.len()).context(\"WinFsp callback probe is too large\")?;\n    stream.write_all(&length.to_be_bytes()).await?;\n    stream.write_all(&bytes).await?;\n    stream.flush().await?;\n    let mut response_length = [0_u8; 4];\n    stream.read_exact(&mut response_length).await?;\n    let length = u32::from_be_bytes(response_length) as usize;\n    if length == 0 || length > SERVICE_MAX_CALLBACK_BYTES {\n        bail!(\"WinFsp callback response exceeds limit\");\n    }\n    let mut response_bytes = vec![0_u8; length];\n    stream.read_exact(&mut response_bytes).await?;\n    let response: StorageFilesystemResponseV2 =\n        serde_json::from_slice(&response_bytes).context(\"decode WinFsp callback probe\")?;\n    if response.protocol_version != STORAGE_FILESYSTEM_PROTOCOL_V2 {\n        bail!(\"WinFsp callback probe protocol mismatch\");\n    }\n    if response.request_id != request.request_id {\n        bail!(\"WinFsp callback probe correlation mismatch\");\n    }\n    match response.outcome {\n        StorageFilesystemOutcomeV2::Success(_) => Ok(()),\n        StorageFilesystemOutcomeV2::Failure(StorageFilesystemFailureV1 { code, message }) => {\n            bail!(\"WinFsp callback probe failed [{code}]: {message}\")\n        },\n    }\n}\n\nasync fn private_service_loop(\n    filesystem: FileSystem,\n    listener: local_transport::LocalListener,\n    launch: &StorageProviderServiceLaunchV1,\n) -> Result<()> {\n    let mut filesystem = Some(filesystem);\n    let mut poll = tokio::time::interval(SERVICE_POLL);\n    loop {\n        tokio::select! {","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-winfsp/src/win.rs#L351-L387","documentation":"probe_callback correlates responses with requests via request_id. If the response's request_id differs from the probe request's id, the reply is rejected — it is stale, duplicated, or belongs to another probe.","triggerScenarios":"run_private_service -> probe_callback when the responder echoes a request_id other than the one in the outgoing request: replayed responses from a prior probe, shared callback_path serving multiple daemons, or a responder that doesn't copy the id field.","commonSituations":"Multiple mount daemons sharing one callback socket so answers interleave; a persistent responder caching and replaying old responses; a responder implementation bug that hardcodes or regenerates request_id instead of echoing it.","solutions":["Fix the responder to echo the exact request_id from the incoming probe into the response.","Give each daemon its own callback_path (derive from lease) so responses cannot cross-contaminate.","Purge stale queued responses on the callback socket before probing.","Ensure the probe is not retried against a socket with in-flight old replies."],"exampleFix":"// before (responder)\nStorageFilesystemResponseV2 { request_id: fixed_id(), .. }\n// after\nStorageFilesystemResponseV2 { request_id: request.request_id.clone(), .. }","handlingStrategy":"type-guard","validationCode":"fn response_correlates(req: &StorageFilesystemRequest, resp: &StorageFilesystemResponseV2) -> bool {\n    resp.request_id == req.request_id\n}","typeGuard":"fn is_reply_to(req: &StorageFilesystemRequest, resp: &StorageFilesystemResponseV2) -> bool {\n    resp.request_id == req.request_id\n}","tryCatchPattern":"match probe_callback(&launch, &request).await {\n    Err(e) if e.to_string().contains(\"correlation mismatch\") => {\n        // drain stale replies from the shared socket, then re-probe with a fresh request_id\n        Err(e)\n    },\n    other => other,\n}","preventionTips":["Always echo request_id verbatim in the responder.","Never share one callback socket between multiple daemons.","Drop queued replies older than the current probe before matching."],"tags":["protocol","correlation","winfsp"],"backgroundTag":"unexpected-response-shape","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}