astrid-runtime/astrid · error
FUSE service control request exceeds limit
Error message
FUSE service control request exceeds limit
What it means
The FUSE control socket reads newline-delimited JSON requests capped at MAX_CONTROL_BYTES. A line that is empty (EOF) or longer than the limit is rejected with this error instead of being parsed, protecting the service from oversized or truncated control requests.
Source
Thrown at crates/astrid-storage-provider-fuse/src/service.rs:123
async fn service_loop(
listener: &tokio::net::UnixListener,
launch: &StorageProviderServiceLaunchV1,
session: &mut Option<FuseBackgroundSession>,
) -> Result<()> {
let mut poll = tokio::time::interval(SERVICE_POLL);
loop {
tokio::select! {
accepted = listener.accept() => {
let (mut stream, _) = accepted.context("accept FUSE service control")?;
let mut line = String::new();
let reader = tokio::io::BufReader::new(&mut stream);
let read = reader
.take((MAX_CONTROL_BYTES + 1) as u64)
.read_line(&mut line)
.await
.context("read FUSE service control request")?;
if read == 0 || line.len() > MAX_CONTROL_BYTES {
bail!("FUSE service control request exceeds limit");
}
let request: KernelControlRequest = serde_json::from_str(&line)
.context("decode FUSE service control request")?;
let (response, stop) = match request {
KernelControlRequest::Status { token } if token == launch.parent.token => {
(KernelControlResponse::Ready, false)
},
KernelControlRequest::Stop { token } if token == launch.parent.token => {
let response = match session.take() {
Some(session) => match tokio::task::spawn_blocking(|| session.umount_and_join()).await {
Ok(Ok(())) => KernelControlResponse::Stopped,
Ok(Err(error)) => failure_response("unmount", &error.to_string()),
Err(error) => failure_response("unmount", &error.to_string()),
},
None => KernelControlResponse::Stopped,
};
if matches!(&response, KernelControlResponse::Stopped) {
let _ = local_transport::remove_endpoint(&launch.control_path);View on GitHub (pinned to affd8760f4)
Solutions
- Keep control requests under MAX_CONTROL_BYTES — trim payloads (e.g. paths, tokens) sent to the socket.
- Ensure every request is a single newline-terminated JSON line written atomically.
- Check the client for errors that cause premature disconnect (read==0) or partial writes.
- Serialize requests with serde_json to one compact line rather than hand-rolled formatting.
- If legitimate requests need more space, raise MAX_CONTROL_BYTES in the service (both sides) consistently.
Example fix
// before stream.write_all(payload.as_bytes())?; // missing newline / oversized // after let line = serde_json::to_string(&request)?; assert!(line.len() <= MAX_CONTROL_BYTES); stream.write_all(line.as_bytes())?; stream.write_all(b"\n")?;
Defensive patterns
Strategy: validation
Validate before calling
let line = serde_json::to_string(&request)?;
if line.len() + 1 > MAX_CONTROL_BYTES {
return Err("control request too large");
}
assert!(line.contains('\n') == false); Try / catch
match write_request(stream, &req).await {
Err(e) if e.to_string().contains("exceeds limit") => trim_payload_and_retry(),
other => other,
} Prevention
- Write each request as one newline-terminated compact JSON line
- Keep payloads well under MAX_CONTROL_BYTES
- Handle server EOF: reconnect before sending again
- Keep MAX_CONTROL_BYTES in sync between client and service
When it happens
Trigger: `service_loop` reads from the control connection with `take(MAX_CONTROL_BYTES + 1).read_line()`, and either the peer closed the connection (`read == 0`) or the received line exceeds MAX_CONTROL_BYTES, causing `bail!`.
Common situations: A client sends a huge or malformed request to the control socket; a truncated write leaves a line without a newline so read_line hits the cap; a client connects and disconnects without sending anything; a probe/writer bug double-encodes payloads.
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
- FUSE control request exceeds the bounded frame size
- FUSE service control response exceeds the bounded frame size
- detached FUSE service exceeded the startup response size
- FUSE callback probe correlation mismatch
- opaque capsule assets cannot be symlinks: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/7ed7b26afeb300a9.
Report an issue: GitHub.