astrid-runtime/astrid · error
mount callback frame exceeds limit
Error message
mount callback frame exceeds limit
What it means
The mount IPC callback protocol frames each request with a big-endian u32 length; a frame declaring a length above MAX_CALLBACK_FRAME_BYTES is rejected before any body is read. This prevents a malformed or malicious peer from making the server allocate an unbounded buffer.
Solutions
- Ensure the client and server are the same version so both agree on frame limits and framing
- Restart both ends of the mount connection to resynchronize the stream
- Check what is actually connecting to the callback socket — reject/fix rogue or wrong clients
- If limits legitimately changed, raise MAX_CALLBACK_FRAME_BYTES consistently on both sides
Defensive patterns
Strategy: validation
Validate before calling
// client side: check the frame before writing it
if payload.len() > MAX_CALLBACK_FRAME_BYTES {
return Err("callback frame too large; split or reject");
} Try / catch
match err.downcast_ref::<io::Error>() {
Some(e) if e.kind() == io::ErrorKind::InvalidData && msg.contains("frame exceeds limit") => {
// resynchronize: drop the connection and reconnect with matching framing
reconnect_mount()?;
}
_ => return Err(err),
} Prevention
- Keep client and server versions in lockstep for the callback protocol
- Only connect the intended client to the callback socket
- Cap your own request payloads well under MAX_CALLBACK_FRAME_BYTES
When it happens
Trigger: `read_request` (called by `handle_connection`) reads the 4-byte length prefix, converts it to usize, and finds `length > MAX_CALLBACK_FRAME_BYTES`. Caused by protocol desync (garbage bytes interpreted as a length), a buggy/incompatible client version, or a corrupted stream.
Common situations: Mixing client and server versions with different framing; connecting a wrong process/socket to the mount callback port; binary garbage after an earlier partial read desynchronized framing.
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
- 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
- FSKit callback probe correlation mismatch
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/233f5ba8b805324b.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-kernel/src/storage_mount.rs:576
};
let response = dispatch_request(&kernel, &state, request).await;
if write_response(&mut stream, response).await.is_err() {
return;
}
}
}
#[cfg(any(unix, windows))]
async fn read_request(stream: &mut LocalStream) -> Result<Option<CallbackRequest>, io::Error> {
let mut length = [0_u8; 4];
match stream.read_exact(&mut length).await {
Ok(_) => {},
Err(error) if error.kind() == io::ErrorKind::UnexpectedEof => return Ok(None),
Err(error) => return Err(error),
}
let length = u32::from_be_bytes(length) as usize;
if length > MAX_CALLBACK_FRAME_BYTES {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"mount callback frame exceeds limit",
));
}
let mut bytes = vec![0_u8; length];
stream.read_exact(&mut bytes).await?;
let protocol = serde_json::from_slice::<ProtocolProbe>(&bytes)
.map_err(io::Error::other)?
.protocol_version;
if protocol == STORAGE_FILESYSTEM_PROTOCOL_V2 {
let request = serde_json::from_slice::<StorageFilesystemRequestV2>(&bytes)
.map_err(io::Error::other)?;
let operation = decode_operation_v2(request.operation)?;
Ok(Some(CallbackRequest {
request: StorageFilesystemRequestV1 {
protocol_version: STORAGE_FILESYSTEM_PROTOCOL_V1,
request_id: request.request_id,
lease_token: request.lease_token,View on GitHub (pinned to affd8760f4)