astrid-runtime/astrid · error
detached FUSE service exceeded the startup response size
Error message
detached FUSE service exceeded the startup response size
What it means
read_service_startup reads a single JSON ServiceStartup line from the detached FUSE service's stdout, bounded by a 64 KiB take() limit. If the line read back exceeds 64*1024 bytes, the parent concludes the child wrote garbage or a runaway payload instead of the expected compact startup response and bails with this error. It is a protocol sanity check protecting the parent from unbounded/unexpected child output.
Source
Thrown at crates/astrid-storage-provider-fuse/src/main.rs:704
stdin.write_all(b"\n").await?;
drop(stdin);
let stdout = child
.stdout
.take()
.context("FUSE service stdout is unavailable")?;
let mut line = String::new();
let reader = tokio::io::BufReader::new(stdout);
let read = tokio::time::timeout(SERVICE_STARTUP_TIMEOUT, async {
let mut limited = reader.take(64 * 1024 + 1);
limited.read_line(&mut line).await
})
.await
.context("timed out waiting for the FUSE service")??;
if read == 0 {
bail!("detached FUSE service exited before readiness");
}
if line.len() > 64 * 1024 {
bail!("detached FUSE service exceeded the startup response size");
}
match serde_json::from_str(&line)? {
ServiceStartup::Ready {
mount_id,
pid,
access,
} => {
if !control_path.exists() {
bail!("detached FUSE service did not retain its control endpoint");
}
if pid == 0 {
bail!("detached FUSE service returned an invalid process identity");
}
Ok(ControlReady {
mount_id,
pid,
access,
})View on GitHub (pinned to affd8760f4)
Solutions
- Rebuild/reinstall the FUSE provider service binary so both sides use the same startup protocol version
- Check the service (and any wrapper command in ServiceLaunch) for code that logs to stdout; route logs to stderr
- Capture the raw stdout line (e.g. run the service in the foreground) and inspect what it prints before readiness
- Verify no shell wrapper or alias echoes the JSON launch config piped to stdin
Example fix
// before: service prints banner + JSON to stdout
println!("fuse service starting, launch={launch:?}");
println!("{}", serde_json::to_string(&startup)?);
// after: only the single JSON line on stdout, everything else on stderr
eprintln!("fuse service starting");
println!("{}", serde_json::to_string(&startup)?); Defensive patterns
Strategy: validation
Validate before calling
// Parent-side guard before parsing child output
let line = read_startup_line_limited(child_stdout, 64 * 1024).await?;
if line.len() > 64 * 1024 { return Err(anyhow!("startup line exceeds protocol limit")); }
if !line.starts_with('{') { return Err(anyhow!("startup output is not JSON: {:?}", &line[..line.len().min(80)])); } Type guard
fn looks_like_startup(line: &str) -> bool {
line.len() <= 64 * 1024 && serde_json::from_str::<ServiceStartup>(line).is_ok()
} Try / catch
match read_service_startup(&mut child, &launch, &control_path).await {
Ok(ready) => proceed(ready),
Err(e) if e.to_string().contains("exceeded the startup response size") => {
// capture raw child stdout/stderr for diagnosis, then fail
diagnose_protocol_mismatch(&child);
}
Err(e) => return Err(e),
} Prevention
- Route all service logging to stderr; reserve stdout exclusively for the single JSON startup line
- Keep parent and service binaries versioned and deployed together
- Add a startup-protocol integration test that asserts the child emits exactly one <=64KiB JSON line
- Never wrap the service in scripts that echo stdin back to stdout
When it happens
Trigger: The FUSE service child process writes a startup line longer than 64 KiB on stdout before the newline — e.g. a corrupted or incompatible binary that echoes debug/launch-config data, logs to stdout instead of stderr, or a build whose ServiceStartup serialization ballooned.
Common situations: Running a mismatched/older version of the service binary that doesn't speak the one-line-JSON startup protocol; a wrapper script or shell echoing the stdin launch config back; stdout redirected or multiplexed with verbose logging.
Related errors
- detached FUSE service did not retain its control endpoint
- detached FUSE service returned an invalid process identity
- FUSE service control request exceeds limit
- 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/c08ae02b981bca05.
Report an issue: GitHub.