astrid-runtime/astrid · error

FUSE control request exceeds the bounded frame size

Error message

FUSE control request exceeds the bounded frame size

What it means

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.

Source

Thrown at crates/astrid-storage-provider-fuse/src/control.rs:151

        })?;
    }
    if let Some(parent) = path.parent() {
        astrid_core::platform_fs::ensure_private_directory(parent)?;
    }
    let listener = StdUnixListener::bind(path)
        .with_context(|| format!("bind FUSE service control socket {}", path.display()))?;
    std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o600))?;
    tokio::net::UnixListener::from_std(listener)
        .context("convert FUSE control listener to the async runtime")
}

/// Send one newline-delimited control request and read one response.
pub(crate) fn call_control(path: &Path, request: &ControlRequest) -> Result<ControlResponse> {
    let mut stream = UnixStream::connect(path)
        .with_context(|| format!("connect FUSE service control socket {}", path.display()))?;
    let bytes = serde_json::to_vec(request)?;
    if bytes.len() >= MAX_CONTROL_FRAME_BYTES {
        bail!("FUSE control request exceeds the bounded frame size");
    }
    stream.write_all(&bytes)?;
    stream.write_all(b"\n")?;
    stream.flush()?;
    let mut reader = BufReader::new(stream);
    read_control_response(&mut reader)
}

fn read_control_response(reader: &mut BufReader<UnixStream>) -> Result<ControlResponse> {
    let mut line = String::new();
    let mut limited = reader.take((MAX_CONTROL_FRAME_BYTES + 1) as u64);
    limited
        .read_line(&mut line)
        .context("read FUSE service control response")?;
    if line.len() > MAX_CONTROL_FRAME_BYTES {
        bail!("FUSE service control response exceeds the bounded frame size");
    }
    serde_json::from_str(&line).context("decode FUSE service control response")

View on GitHub (pinned to affd8760f4)

Solutions

  1. Reduce the payload size of the ControlRequest (shorten paths, drop or compress large metadata fields).
  2. Move bulk data out of the control channel — reference it by id/handle instead of embedding it.
  3. Raise MAX_CONTROL_FRAME_BYTES consciously on both the client and the FUSE service so the frame protocol stays consistent.
  4. Validate the serialized size before calling call_control and split or reject oversized requests at the caller.

Example fix

// before
let req = ControlRequest::Mount { lease: huge_inline_blob };
call_control(&sock, &req)?;
// after
let bytes = serde_json::to_vec(&req)?;
assert!(bytes.len() < 64 * 1024, "control request too large");
call_control(&sock, &req)?;
Defensive patterns

Strategy: validation

Validate before calling

let bytes = serde_json::to_vec(&request)?;
if bytes.len() >= 64 * 1024 { return Err(anyhow!("control request too large")); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

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


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/9b10f3b110641236. Report an issue: GitHub.