Zackriya-Solutions/meetily · critical · anyhow::Error
Sidecar closed stdout (process may have crashed)
Error message
Sidecar closed stdout (process may have crashed)
What it means
read_response got EOF on the sidecar's stdout: read_line returned zero bytes, meaning the llama-helper process has exited. The helper crashed or was killed - fatal model-load error inside the helper, a panic, the OOM killer, or an external kill. stderr is inherited (Stdio::inherit), so the helper's own dying message usually appears in the app log just before this error.
Source
Thrown at frontend/src-tauri/src/summary/summary_engine/sidecar.rs:406
}
}
}
/// Read a single line response from stdout
async fn read_response(&self) -> Result<String> {
let mut stdout_lock = self.stdout_reader.lock().await;
let reader = stdout_lock
.as_mut()
.ok_or_else(|| anyhow!("Sidecar not running"))?;
let mut line = String::new();
reader
.read_line(&mut line)
.await
.context("Failed to read response from stdout")?;
if line.is_empty() {
return Err(anyhow!("Sidecar closed stdout (process may have crashed)"));
}
Ok(line.trim().to_string())
}
/// Send ping to keep sidecar alive
async fn send_ping(&self) -> Result<()> {
let request = serde_json::json!({"type": "ping"}).to_string();
let timeout = Duration::from_secs(5);
// Note: We don't use send_request here to avoid incrementing active_request_count
// for internal health checks, as that would prevent graceful shutdown
// Write request
{
let mut stdin_lock = self.stdin_writer.lock().await;
if let Some(stdin) = stdin_lock.as_mut() {
stdin.write_all(request.as_bytes()).await?;View on GitHub (pinned to 0281737d87)
Solutions
- Check the app log for the helper's stderr immediately before the EOF - it names the real cause (model load failure, allocation failure, panic)
- If memory was the cause, free RAM or use a smaller summary model
- Verify the model path passed to ensure_running still exists and is a valid GGUF
- Rebuild llama-helper from the same source revision as the app so the JSON-line protocol matches
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight: the model must be readable and the process alive before sending
if !model_path.is_file() { return Err(anyhow!("model file missing: {:?}", model_path)); }
if !sidecar.is_healthy() { sidecar.ensure_running(model_path.clone()).await?; } Try / catch
match sidecar.send_request(req, timeout).await {
Err(e) if e.to_string().contains("closed stdout") => {
log::error!("sidecar crashed; stderr (inherited) shows the cause just above");
sidecar.ensure_running(model_path.clone()).await?; // respawn
match sidecar.send_request(req, timeout).await {
Err(e2) if e2.to_string().contains("closed stdout") =>
Err(anyhow!("sidecar crashes immediately; check RAM and rebuild llama-helper")),
other => other,
}
}
other => other,
}? Prevention
- Watch the app log (stderr is inherited) for the helper's own crash message before this EOF error
- Keep helper and app built from the same source revision so the line protocol matches
- Cap model size to available RAM; an OOM-killed helper is the most common crash cause
When it happens
Trigger: llama-helper dies while handling a request: out-of-memory loading or running a large GGUF, a panic in the helper, an invalid/unreadable model path passed at spawn, or an external signal (OOM killer, task manager, container cgroup kill).
Common situations: Large model on machines with tight RAM (OOM kill), model file deleted or moved after the sidecar loaded it, helper binary built from a different source revision whose stdin/stdout protocol no longer matches the app.
Related errors
- Failed to wait for ffmpeg process: {}
- Failed to get stdin
- Generation failed: {}
- Sidecar error: {}
- Failed to determine project root
AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16).
Data as JSON: /api/errors/680f80d393c8c8c0.
Report an issue: GitHub.