{"record":{"id":"a0bf369ed09e40fb","repo":"astrid-runtime/astrid","slug":"fuse-callback-response-exceeds-the-bounded-frame-s","errorCode":null,"errorMessage":"FUSE callback response exceeds the bounded frame size","messagePattern":"FUSE callback response exceeds the bounded frame size","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-fuse/src/service.rs","lineNumber":331,"sourceCode":"    stream.flush().await?;\n    let response = read_callback_response(&mut stream).await?;\n    if response.request_id != request.request_id {\n        bail!(\"FUSE callback probe correlation mismatch\");\n    }\n    match response.outcome {\n        StorageFilesystemOutcomeV2::Success(_) => Ok(()),\n        StorageFilesystemOutcomeV2::Failure(StorageFilesystemFailureV1 { code, message }) => {\n            bail!(\"FUSE callback probe failed [{code}]: {message}\")\n        },\n    }\n}\n\nasync fn read_callback_response(stream: &mut LocalStream) -> Result<StorageFilesystemResponseV2> {\n    let mut length = [0_u8; 4];\n    stream.read_exact(&mut length).await?;\n    let length = u32::from_be_bytes(length) as usize;\n    if length == 0 || length > MAX_CALLBACK_BYTES {\n        bail!(\"FUSE callback response exceeds the bounded frame size\");\n    }\n    let mut bytes = vec![0_u8; length];\n    stream.read_exact(&mut bytes).await?;\n    let response: StorageFilesystemResponseV2 =\n        serde_json::from_slice(&bytes).context(\"decode FUSE callback probe\")?;\n    if response.protocol_version != STORAGE_FILESYSTEM_PROTOCOL_V2 {\n        bail!(\"FUSE callback probe protocol mismatch\");\n    }\n    Ok(response)\n}\n\n#[cfg(unix)]\nfn parent_is_alive(\n    parent: &astrid_core::storage_filesystem::StorageProviderParentLifetimeV1,\n) -> bool {\n    use nix::sys::signal::kill;\n    use nix::unistd::Pid;\n","sourceCodeStart":313,"sourceCodeEnd":349,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-fuse/src/service.rs#L313-L349","documentation":"read_callback_response() reads a 4-byte big-endian length prefix followed by a JSON body over the local callback stream. If the declared frame length is 0 or exceeds MAX_CALLBACK_BYTES, it refuses to allocate and bails, protecting the provider from unbounded allocations on the local stream.","triggerScenarios":"The peer on the LocalStream writes a length prefix of 0 or one greater than MAX_CALLBACK_BYTES before the response body — e.g. a corrupted writer, a peer that isn't speaking the framed protocol, or a response payload that legitimately exceeds the bound.","commonSituations":"A stale or mismatched process is attached to the local stream; the callback peer crashed mid-frame and wrote garbage; protocol drift between provider versions makes the reader interpret a non-length field as the frame size.","solutions":["Check the FUSE provider callback peer is the correct, matching-version process speaking the length-prefixed STORAGE_FILESYSTEM_PROTOCOL_V2 framing.","Restart the callback peer / relaunch the provider so both ends start with a clean stream state.","If legitimate responses are too large, raise MAX_CALLBACK_BYTES on both sides consistently.","Log the offending length value to confirm whether the peer is writing garbage or genuinely oversized payloads."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// On the peer side, before writing:\nlet bytes = serde_json::to_vec(&response)?;\nassert!(bytes.len() > 0 && bytes.len() <= MAX_CALLBACK_BYTES, \"callback frame out of bounds\");","typeGuard":null,"tryCatchPattern":"// Rust\nmatch probe_callback(&mut stream, request).await {\n    Err(e) if e.to_string().contains(\"bounded frame size\") => {\n        // restart the peer / relaunch; the stream framing is desynchronized\n    }\n    other => other?,\n}","preventionTips":["Keep callback peers version-matched so framing never drifts","Restart peers cleanly; never reuse streams after a partial write","Keep response payloads within MAX_CALLBACK_BYTES on both sides"],"tags":["fuse","framing","payload-size","ipc"],"backgroundTag":"payload-too-large","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}