zeroclaw-labs/zeroclaw · error

lucid command timed out after {}ms

Error message

lucid command timed out after {}ms

What it means

The lucid CLI subprocess exceeded its timeout window; this branch is reached only after the child was successfully terminated and reaped, so no orphaned process remains. It is the plain timeout signal for lucid command latency, raised from wait_for_lucid_child when the deadline elapses.

Source

Thrown at crates/zeroclaw-memory/src/lucid.rs:303

                let cleanup_error = child.kill().await.err().map(|error| error.to_string());
                ::zeroclaw_log::record!(
                    ERROR,
                    ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Timeout)
                        .with_outcome(::zeroclaw_log::EventOutcome::Failure)
                        .with_attrs(::serde_json::json!({
                            "command": lucid_cmd,
                            "timeout_ms": timeout_window.as_millis() as u64,
                            "cleanup_error": cleanup_error,
                        })),
                    "lucid command timed out"
                );
                if let Some(cleanup_error) = cleanup_error {
                    anyhow::bail!(
                        "lucid command timed out after {}ms; failed to terminate and reap child: {cleanup_error}",
                        timeout_window.as_millis()
                    );
                }
                anyhow::bail!(
                    "lucid command timed out after {}ms",
                    timeout_window.as_millis()
                );
            }
        };

        if !status.success() {
            let stderr = String::from_utf8_lossy(&stderr_bytes);
            anyhow::bail!("lucid command failed: {stderr}");
        }

        Ok(String::from_utf8_lossy(&stdout_bytes).to_string())
    }

    async fn run_lucid_command(
        &self,
        args: &[String],
        timeout_window: Duration,

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Increase the timeout override: `recall_timeout_ms` / `store_timeout_ms` in `[storage.lucid.<alias>]`.
  2. Reduce reliance on lucid for hot paths — recall skips lucid entirely when local hits reach the limit/threshold, so keeping the local sqlite store warm avoids the call.
  3. Health-check or pre-warm the lucid binary/endpoint so typical commands fit inside the window.

Example fix

# before
[storage.lucid.main]
recall_timeout_ms = 2000

# after
[storage.lucid.main]
recall_timeout_ms = 30000
Defensive patterns

Strategy: retry

Try / catch

let mut attempt = 0;
loop {
    attempt += 1;
    match run_lucid_command(&args).await {
        Ok(out) => break Ok(out),
        Err(e) if e.to_string().contains("lucid command timed out") && attempt < 3 => {
            tokio::time::sleep(Duration::from_millis(200 * u64::from(attempt))).await;
        }
        Err(e) => break Err(e),
    }
}

Prevention

When it happens

Trigger: Any lucid command (typically the recall path's lucid query or a store sync) taking longer than the configured window while the system can still kill and reap the child cleanly.

Common situations: Cold-start latency of the lucid binary; slow or distant lucid service; timeouts tuned in one environment and reused in a slower one; lucid service under load.

Understand the failure class

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/dcb2fabd7cdc465a. Report an issue: GitHub.