astrid-runtime/astrid · error
FSKit service control request exceeds limit
Error message
FSKit service control request exceeds limit
What it means
read_control reads one newline-delimited JSON control request from the service socket using a take(MAX_CONTROL_BYTES + 1) cap. If the line is empty (EOF) or longer than MAX_CONTROL_BYTES, it is rejected. This bounds memory per control message and treats EOF-with-no-data as a protocol error.
Source
Thrown at crates/astrid-storage-provider-fskit/src/service.rs:317
_ = poll.tick() => {
if !parent_is_alive(&launch.parent) || probe_callback(launch).await.is_err() {
return Ok(());
}
},
}
}
}
async fn read_control(stream: &mut LocalStream) -> Result<ControlRequest> {
let mut line = String::new();
let reader = tokio::io::BufReader::new(stream);
let read = reader
.take((MAX_CONTROL_BYTES + 1) as u64)
.read_line(&mut line)
.await
.context("read FSKit service control request")?;
if read == 0 || line.len() > MAX_CONTROL_BYTES {
bail!("FSKit service control request exceeds limit");
}
serde_json::from_str(&line).context("decode FSKit service control request")
}
async fn write_control(stream: &mut LocalStream, response: &ControlResponse) -> Result<()> {
let bytes = serde_json::to_vec(response)?;
stream.write_all(&bytes).await?;
stream.write_all(b"\n").await?;
stream.flush().await.context("flush FSKit service control")
}
#[cfg(unix)]
fn parent_is_alive(
parent: &astrid_core::storage_filesystem::StorageProviderParentLifetimeV1,
) -> bool {
use nix::sys::signal::kill;
use nix::unistd::Pid;
View on GitHub (pinned to affd8760f4)
Solutions
- Ensure control clients send newline-terminated JSON within MAX_CONTROL_BYTES
- Split oversized control requests or extend MAX_CONTROL_BYTES deliberately if legitimate payloads grew
- Verify no stray process is writing to the control socket path
- Check the client didn't crash mid-write (EOF case) and reconnect
Example fix
// client side // before stream.write_all(payload)?; // after stream.write_all(payload)?; stream.write_all(b"\n")?;
Defensive patterns
Strategy: validation
Validate before calling
fn control_payload_ok(json: &str, max: usize) -> bool { json.len() <= max && json.ends_with('\n') } Try / catch
match read_control(&mut reader).await { Err(e) if e.to_string().contains("exceeds limit") => { drop_client(); continue; } other => other } Prevention
- Always terminate control requests with a newline
- Keep control messages small and split large payloads
- Check for unexpected writers on the control socket
- Handle client disconnects (EOF) as a normal reconnect case
When it happens
Trigger: read_control receives either 0 bytes before newline (client disconnected without sending) or a line exceeding MAX_CONTROL_BYTES — e.g. a client sending a huge un-terminated line or binary garbage on the control socket.
Common situations: A client writing a control request without a trailing newline then being truncated; an over-large serialized request; something other than the intended client connected to the socket and wrote junk.
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
- IPC frame too large: {len} bytes
- FSKit callback response exceeds the bounded frame size
- provider request exceeds limit
- FUSE callback response exceeds the bounded frame size
- IPC frame overflow
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/5129e941261c9164.
Report an issue: GitHub.