xai-org/grok-build · error

spawn mermaid-render thread

Error message

spawn mermaid-render thread

What it means

`spawn_worker` spawns the dedicated mermaid-render thread and panics with 'spawn mermaid-render thread' if `std::thread::Builder::spawn` fails. The worker thread renders mermaid diagrams to PNG off the UI thread, so without it rendering cannot proceed at all.

Source

Thrown at crates/codegen/xai-grok-pager/src/app/mermaid_worker.rs:245

                        if writes_since_sweep >= SWEEP_EVERY_N_WRITES {
                            writes_since_sweep = 0;
                            if let Some(dir) = job.out_path.parent() {
                                // Off the draw path (worker thread); keeps the session's mermaid/ dir bounded within a session
                                sweep_session_cache(dir, SESSION_DISK_CAP_BYTES);
                            }
                        }
                    }
                    let result = MermaidResult {
                        key: job.key,
                        outcome,
                    };
                    if result_tx.send(result).is_err() {
                        return; // Receiver dropped; the view is gone.
                    }
                }
            }
        })
        .expect("spawn mermaid-render thread");

    (job_tx, result_rx)
}

/// Coalesce `first` plus every job already queued on `rx` into a per-[`MermaidCacheKey`] map where the latest job for each key wins.
/// `IndexMap` keeps FIFO order across distinct keys, so independent diagrams still render in order.
fn drain_coalesced(
    first: MermaidJob,
    rx: &Receiver<MermaidJob>,
) -> IndexMap<MermaidCacheKey, MermaidJob> {
    let mut pending: IndexMap<MermaidCacheKey, MermaidJob> = IndexMap::new();
    pending.insert(first.key.clone(), first);
    while let Ok(job) = rx.try_recv() {
        pending.insert(job.key.clone(), job);
    }
    pending
}

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Check and raise thread limits: `ulimit -u`, container `pids.max` cgroup setting.
  2. Free memory or reduce the configured worker stack size so allocation succeeds.
  3. Check for thread leaks elsewhere in the process (join or terminate long-lived workers).
  4. Propagate the spawn error to the caller and degrade gracefully (render inline or report mermaid unavailable).

Example fix

// before
.expect("spawn mermaid-render thread");
// after
.map_err(|e| MermaidError::WorkerSpawn(e.to_string()))?;
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight thread-creation capability
match std::thread::Builder::new().stack_size(64 * 1024).spawn(|| {}) {
    Ok(h) => { h.join().ok(); }
    Err(e) => eprintln!("thread limits exhausted: {e}"),
}

Try / catch

match thread::Builder::new().name("mermaid-render").spawn(worker_loop) {
    Ok(handle) => handle,
    Err(e) => return Err(MermaidError::WorkerSpawn(e.to_string())),
}

Prevention

When it happens

Trigger: `std::thread::Builder::spawn` returning Err — the OS refused to create the thread, almost always due to resource limits.

Common situations: Hitting the process/thread limit (ulimit -u, cgroup pids.max); insufficient stack memory to reserve the worker stack under memory pressure; running inside a restricted sandbox/container with thread creation blocked.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/e21933f787dd98f9. Report an issue: GitHub.