astrid-runtime/astrid · error
FUSE callback response exceeds the bounded frame size
Error message
FUSE callback response exceeds the bounded frame size
What it means
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.
Source
Thrown at crates/astrid-storage-provider-fuse/src/service.rs:331
stream.flush().await?;
let response = read_callback_response(&mut stream).await?;
if response.request_id != request.request_id {
bail!("FUSE callback probe correlation mismatch");
}
match response.outcome {
StorageFilesystemOutcomeV2::Success(_) => Ok(()),
StorageFilesystemOutcomeV2::Failure(StorageFilesystemFailureV1 { code, message }) => {
bail!("FUSE 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!("FUSE 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 FUSE callback probe")?;
if response.protocol_version != STORAGE_FILESYSTEM_PROTOCOL_V2 {
bail!("FUSE callback probe protocol mismatch");
}
Ok(response)
}
#[cfg(unix)]
fn parent_is_alive(
parent: &astrid_core::storage_filesystem::StorageProviderParentLifetimeV1,
) -> bool {
use nix::sys::signal::kill;
use nix::unistd::Pid;
View on GitHub (pinned to affd8760f4)
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.
Defensive patterns
Strategy: validation
Validate before calling
// On the peer side, before writing: let bytes = serde_json::to_vec(&response)?; assert!(bytes.len() > 0 && bytes.len() <= MAX_CALLBACK_BYTES, "callback frame out of bounds");
Try / catch
// Rust
match probe_callback(&mut stream, request).await {
Err(e) if e.to_string().contains("bounded frame size") => {
// restart the peer / relaunch; the stream framing is desynchronized
}
other => other?,
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- opaque capsule assets cannot be symlinks: {}
- provider request exceeds limit
- FSKit service launch exceeds limit
- FSKit callback response exceeds the bounded frame size
- FSKit service control request exceeds limit
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/a0bf369ed09e40fb.
Report an issue: GitHub.