clockworklabs/SpacetimeDB · error · anyhow::Error

Failed to check client process status

Error message

Failed to check client process status: {}

What it means

While `spacetime dev` polls the spawned client process, the OS-level waitpid call behind try_wait() returned an error instead of a status. This means the CLI can no longer observe the child (classic cause: ECHILD, the child was already reaped by something else, e.g. a signal handler, an exiting wrapper shell that detached the grandchild, or a container/PID-namespace quirk). It is rare infrastructure noise, not a bug in your module.

Solutions

  1. Remove backgrounding/daemonizing from the client command so the spawned process stays in the foreground
  2. Simply rerun `spacetime dev`; a one-off reap race usually does not recur
  3. Upgrade the SpacetimeDB CLI in case the polling logic was fixed
  4. Run the client manually in a second terminal instead of through `spacetime dev`

Example fix

# before (spacetime.json)
"client": "nohup npm run dev &"
# after
"client": "npm run dev"
Defensive patterns

Strategy: retry

Try / catch

for attempt in 0..3 {
    match run_dev().await {
        Err(e) if e.to_string().contains("Failed to check client process status") && attempt < 2 => continue,
        rest => break rest,
    }
}

Prevention

When it happens

Trigger: Client command that daemonizes or backgrounds itself (nohup, `&`, a wrapper that execs and exits); process reaped by a supervisor or shell job control before the CLI polls it; running `spacetime dev` inside minimal containers with unusual PID reaping.

Common situations: Client command like `npm run dev &` or a tool that forks to background; tmux/screen job-control interference; occasional flake in CI runners with aggressive process cleanup.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@3653d2ed49 (2026-08-20). Data as JSON: /api/errors/1a4cbe009d7cf57d. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/subcommands/dev.rs:832

    let server_host_url = config.get_host_url(Some(server_for_client))?;
    let mut client_handle = if let Some(ref cmd) = client_command {
        let mut child = start_client_process(cmd, &project_dir, db_name_for_client, &server_host_url)?;

        // Give the process a moment to fail fast (e.g., command not found, missing deps)
        sleep(Duration::from_millis(200)).await;
        match child.try_wait() {
            Ok(Some(status)) if !status.success() => {
                anyhow::bail!(
                    "Client command '{}' failed immediately with exit code: {}",
                    cmd,
                    status
                        .code()
                        .map(|c| c.to_string())
                        .unwrap_or_else(|| "unknown".to_string())
                );
            }
            Err(e) => {
                anyhow::bail!("Failed to check client process status: {}", e);
            }
            _ => {} // Still running or exited successfully (unusual but ok)
        }
        Some(child)
    } else {
        None
    };

    let gitignore = build_gitignore_matcher(&project_dir, &spacetimedb_dir);

    let (tx, rx) = channel();
    let mut watcher: RecommendedWatcher = Watcher::new(
        move |res: Result<Event, notify::Error>| {
            if let Ok(event) = res
                && matches!(
                    event.kind,
                    notify::EventKind::Modify(_) | notify::EventKind::Create(_) | notify::EventKind::Remove(_)
                )

View on GitHub (pinned to 3653d2ed49)