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

  1. Rebuild/upgrade the callback responder so its protocol_version equals STORAGE_FILESYSTEM_PROTOCOL_V2.
  2. Align crate versions of the daemon and callback library (same workspace revision) and re-deploy both.
  3. Confirm the process answering on callback_path is actually the expected astrid callback, not another service.
  4. 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

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


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)