astrid-runtime/astrid · error
FSKit callback probe protocol mismatch
Error message
FSKit callback probe protocol mismatch
What it means
read_callback_response deserializes the framed JSON into StorageFilesystemResponseV2 and requires response.protocol_version to equal STORAGE_FILESYSTEM_PROTOCOL_V2. A different version means the peer speaks an incompatible protocol revision, so the response is rejected rather than misinterpreted.
Solutions
- Upgrade the FSKit extension to the build that speaks STORAGE_FILESYSTEM_PROTOCOL_V2
- Check for a stale extension binary/process and restart the service so the current one is used
- Align the protocol constant across provider and extension (bump both together)
- If migrating intentionally, add a version negotiation step before probing
Example fix
// extension side // before response.protocolVersion = 1 // after response.protocolVersion = STORAGE_FILESYSTEM_PROTOCOL_V2
Defensive patterns
Strategy: validation
Validate before calling
fn protocol_ok(resp: &StorageFilesystemResponseV2) -> bool { resp.protocol_version == STORAGE_FILESYSTEM_PROTOCOL_V2 } Try / catch
if let Err(e) = read_callback_response(&mut stream).await { if e.to_string().contains("protocol mismatch") { report_version_skew(); } } Prevention
- Deploy provider and extension upgrades together
- Add a version handshake before probes
- Restart services after upgrades to kill stale responders
- Pin the protocol constant in a shared definition
When it happens
Trigger: read_callback_response (called by probe_callback) parses a well-framed response whose protocol_version != STORAGE_FILESYSTEM_PROTOCOL_V2 — typically an older or newer extension responding on the socket.
Common situations: Version skew after upgrading the Rust provider but not the bundled FSKit extension (or vice versa); a legacy V1 responder still running; a test stub hard-coding another version constant.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- unsupported provider protocol
- daemon closed the response stream before the final marker
- daemon rejected status request
- daemon returned an unexpected status response
- detached FUSE service exceeded the startup response size
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/3e1a7c18114d07d6.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-storage-provider-fskit/src/service.rs:254
StorageFilesystemOutcomeV2::Failure(StorageFilesystemFailureV1 { code, message }) => {
bail!("FSKit callback probe failed [{code}]: {message}")
},
}
}
async fn read_callback_response(stream: &mut LocalStream) -> Result<StorageFilesystemResponseV2> {
let mut length = [0_u8; 4];
stream.read_exact(&mut length).await?;
let length = u32::from_be_bytes(length) as usize;
if length == 0 || length > MAX_CALLBACK_BYTES {
bail!("FSKit callback response exceeds the bounded frame size");
}
let mut bytes = vec![0_u8; length];
stream.read_exact(&mut bytes).await?;
let response: StorageFilesystemResponseV2 =
serde_json::from_slice(&bytes).context("decode FSKit callback probe")?;
if response.protocol_version != STORAGE_FILESYSTEM_PROTOCOL_V2 {
bail!("FSKit callback probe protocol mismatch");
}
Ok(response)
}
async fn service_loop(
listener: &LocalListener,
launch: &StorageProviderServiceLaunchV1,
mounted: &mut bool,
) -> Result<()> {
let mut poll = tokio::time::interval(SERVICE_POLL);
loop {
tokio::select! {
accepted = local_transport::accept(listener) => {
let mut stream = accepted.context("accept FSKit service control")?;
let request = read_control(&mut stream).await?;
let (response, stop) = match request {
ControlRequest::Status { token } if token == launch.parent.token => {
(ControlResponse::Ready, false)View on GitHub (pinned to affd8760f4)