{"record":{"id":"9b10f3b110641236","repo":"astrid-runtime/astrid","slug":"fuse-control-request-exceeds-the-bounded-frame-siz","errorCode":null,"errorMessage":"FUSE control request exceeds the bounded frame size","messagePattern":"FUSE control request exceeds the bounded frame size","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-fuse/src/control.rs","lineNumber":151,"sourceCode":"        })?;\n    }\n    if let Some(parent) = path.parent() {\n        astrid_core::platform_fs::ensure_private_directory(parent)?;\n    }\n    let listener = StdUnixListener::bind(path)\n        .with_context(|| format!(\"bind FUSE service control socket {}\", path.display()))?;\n    std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o600))?;\n    tokio::net::UnixListener::from_std(listener)\n        .context(\"convert FUSE control listener to the async runtime\")\n}\n\n/// Send one newline-delimited control request and read one response.\npub(crate) fn call_control(path: &Path, request: &ControlRequest) -> Result<ControlResponse> {\n    let mut stream = UnixStream::connect(path)\n        .with_context(|| format!(\"connect FUSE service control socket {}\", path.display()))?;\n    let bytes = serde_json::to_vec(request)?;\n    if bytes.len() >= MAX_CONTROL_FRAME_BYTES {\n        bail!(\"FUSE control request exceeds the bounded frame size\");\n    }\n    stream.write_all(&bytes)?;\n    stream.write_all(b\"\\n\")?;\n    stream.flush()?;\n    let mut reader = BufReader::new(stream);\n    read_control_response(&mut reader)\n}\n\nfn read_control_response(reader: &mut BufReader<UnixStream>) -> Result<ControlResponse> {\n    let mut line = String::new();\n    let mut limited = reader.take((MAX_CONTROL_FRAME_BYTES + 1) as u64);\n    limited\n        .read_line(&mut line)\n        .context(\"read FUSE service control response\")?;\n    if line.len() > MAX_CONTROL_FRAME_BYTES {\n        bail!(\"FUSE service control response exceeds the bounded frame size\");\n    }\n    serde_json::from_str(&line).context(\"decode FUSE service control response\")","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-fuse/src/control.rs#L133-L169","documentation":"This error means the JSON serialization of a FUSE control request was at or above the 64 KiB `MAX_CONTROL_FRAME_BYTES` limit before it was written to the control Unix socket. The library enforces a bounded, newline-delimited frame protocol on the control channel, so it refuses to send any request that could not fit in one frame, preventing unbounded writes and truncated reads. It is thrown from `call_control` in crates/astrid-storage-provider-fuse/src/control.rs:151 after `serde_json::to_vec` but before any bytes hit the socket.","triggerScenarios":"Calling `call_control` with a `ControlRequest` whose serialized JSON is >= 65536 bytes — typically a request embedding an unusually large access description, lease metadata, or path payload.","commonSituations":"Embedding very long paths or bulk metadata in the control request; a protocol/serde change that accidentally inlines a large blob into ControlRequest; constructing requests from untrusted input without size checks.","solutions":["Reduce the payload size of the ControlRequest (shorten paths, drop or compress large metadata fields).","Move bulk data out of the control channel — reference it by id/handle instead of embedding it.","Raise MAX_CONTROL_FRAME_BYTES consciously on both the client and the FUSE service so the frame protocol stays consistent.","Validate the serialized size before calling call_control and split or reject oversized requests at the caller."],"exampleFix":"// before\nlet req = ControlRequest::Mount { lease: huge_inline_blob };\ncall_control(&sock, &req)?;\n// after\nlet bytes = serde_json::to_vec(&req)?;\nassert!(bytes.len() < 64 * 1024, \"control request too large\");\ncall_control(&sock, &req)?;","handlingStrategy":"validation","validationCode":"let bytes = serde_json::to_vec(&request)?;\nif bytes.len() >= 64 * 1024 { return Err(anyhow!(\"control request too large\")); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Measure serialized request size before sending over the control socket","Keep large payloads out of ControlRequest; pass references instead","Keep MAX_CONTROL_FRAME_BYTES identical on client and service"],"tags":["fuse","ipc","payload-too-large","serde"],"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"}