{"record":{"id":"ffb13cb8e2ba7d38","repo":"astrid-runtime/astrid","slug":"mount-callback-response-exceeds-limit","errorCode":null,"errorMessage":"mount callback response exceeds limit","messagePattern":"mount callback response exceeds limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/storage_mount.rs","lineNumber":681,"sourceCode":"        StorageFilesystemOperationV2::Rename { from, to, replace } => {\n            StorageFilesystemOperationV1::Rename { from, to, replace }\n        },\n        StorageFilesystemOperationV2::Sync => StorageFilesystemOperationV1::Sync,\n    })\n}\n\n#[cfg(any(unix, windows))]\nasync fn write_response(\n    stream: &mut LocalStream,\n    response: CallbackResponse,\n) -> Result<(), io::Error> {\n    let bytes = match response {\n        CallbackResponse::V1(response) => serde_json::to_vec(&response),\n        CallbackResponse::V2(response) => serde_json::to_vec(&response),\n    }\n    .map_err(io::Error::other)?;\n    if bytes.len() > MAX_CALLBACK_FRAME_BYTES {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            \"mount callback response exceeds limit\",\n        ));\n    }\n    let length = u32::try_from(bytes.len()).map_err(|_| {\n        io::Error::new(\n            io::ErrorKind::InvalidData,\n            \"mount callback response is too large\",\n        )\n    })?;\n    stream.write_all(&length.to_be_bytes()).await?;\n    stream.write_all(&bytes).await?;\n    stream.flush().await\n}\n\nasync fn dispatch_request(\n    kernel: &Kernel,\n    state: &StorageMountLeaseState,","sourceCodeStart":663,"sourceCodeEnd":699,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/storage_mount.rs#L663-L699","documentation":"write_response serializes a CallbackResponse (V1 or V2) to JSON and refuses to send it if the serialized byte length exceeds MAX_CALLBACK_FRAME_BYTES. This keeps each callback frame within the fixed length-prefix framing the socket protocol uses.","triggerScenarios":"An operation returns a response whose JSON serialization is larger than MAX_CALLBACK_FRAME_BYTES — typically a Read response carrying a huge data blob — and write_response (from handle_connection) rejects it before writing the length prefix.","commonSituations":"A reader requests more bytes than the frame limit allows in one Read reply; MAX_CALLBACK_FRAME_BYTES was shrunk in config/constant while clients still request big reads; a response accidentally embeds large debug data.","solutions":["Cap Read request sizes to fit within MAX_CALLBACK_FRAME_BYTES and return data in multiple reads","If you control the code, align the client's max read size with the kernel's MAX_CALLBACK_FRAME_BYTES constant","Shrink the response payload (remove embedded blobs/metadata) so serialization fits","Enlarge MAX_CALLBACK_FRAME_BYTES only if both kernel and provider are updated together"],"exampleFix":"// before\nlet data = fs.read(path, 0, 64 * 1024 * 1024)?;\n// after\nlet data = fs.read(path, 0, MAX_CALLBACK_FRAME_BYTES - FRAME_OVERHEAD)?;","handlingStrategy":"validation","validationCode":"fn fits_in_callback_frame(bytes_len: usize) -> bool {\n    bytes_len <= MAX_CALLBACK_FRAME_BYTES\n}\n// before issuing a large Read, clamp the request size:\nlet read_len = read_len.min(MAX_CALLBACK_FRAME_BYTES - FRAME_OVERHEAD);","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string() == \"mount callback response exceeds limit\" => {\n        eprintln!(\"response too large: reduce read size or chunk reads\");\n    }\n    other => other?,\n}","preventionTips":["Cap Read request sizes to what one callback frame can carry","Keep client max-read-size in sync with MAX_CALLBACK_FRAME_BYTES","Avoid embedding unbounded blobs or debug data in callback responses"],"tags":["payload","limit","response","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-17T15:17:12.973Z"}