xai-org/grok-build · warning

just created

Error message

just created

What it means

`ensure_mermaid_runtime` lazily creates the `MermaidRuntime` and then unwraps `self.mermaid.as_mut().expect("just created")`. The expect is an internal invariant: the Option was set two lines earlier, so this can only panic if re-entrant mutable access or a panic mid-initialization left the state inconsistent — practically it should be unreachable.

Source

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

    }

    /// Representative content columns for diagram render sizing this frame.
    fn mermaid_content_cols(&self) -> u16 {
        representative_content_cols(self.last_terminal_size.0)
    }

    /// Drive the lazy mermaid work for one tick: poll the worker for finished on-click renders and run each requesting action.
    /// Returns `true` when a redraw is warranted. A no-op until a click is in flight.
    pub fn mermaid_tick(&mut self) -> bool {
        self.poll_mermaid_results()
    }

    /// Lazily create the render runtime (and spawn the worker) on first need.
    fn ensure_mermaid_runtime(&mut self) -> &mut MermaidRuntime {
        if self.mermaid.is_none() {
            self.mermaid = Some(MermaidRuntime::new());
        }
        self.mermaid.as_mut().expect("just created")
    }

    /// Per-session destination path for a diagram's PNG, or `None` until session identity is known (no on-disk cache before then).
    fn mermaid_out_path(&self, key: &MermaidCacheKey) -> Option<PathBuf> {
        // Test override: a hermetic per-test cache dir (no `GROK_HOME` mutation)
        #[cfg(test)]
        if let Some(path) = TEST_MERMAID_DIR.with(|d| {
            d.borrow()
                .as_ref()
                .map(|tmp| tmp.path().join(key.cache_filename()))
        }) {
            return Some(path);
        }
        let dir = crate::prompt_images::session_mermaid_dir(
            self.session.session_id.as_ref(),
            &self.session.cwd,
        )?;
        Some(dir.join(key.cache_filename()))

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Confirm `MermaidRuntime::new()` doesn't panic (it spawns the worker — check error 745 conditions).
  2. Inspect recent refactors of `ensure_mermaid_runtime` to ensure the Some(...) assignment still precedes the expect.
  3. Rewrite to a single expression avoiding the intermediate expect: `self.mermaid.get_or_insert_with(MermaidRuntime::new)`.
  4. If it fires, treat it as a logic bug — add a debug_assert/log capturing how the field was None after assignment.

Example fix

// before
if self.mermaid.is_none() {
    self.mermaid = Some(MermaidRuntime::new());
}
self.mermaid.as_mut().expect("just created")
// after
self.mermaid.get_or_insert_with(MermaidRuntime::new)
Defensive patterns

Strategy: type-guard

Validate before calling

// collapse the lazy-init so no expect is needed
let rt = self.mermaid.get_or_insert_with(MermaidRuntime::new);

Type guard

fn runtime_ready(rt: &Option<MermaidRuntime>) -> bool {
    rt.is_some()
}

Try / catch

// not applicable: invariant panic; use get_or_insert_with to remove it
let rt = self.mermaid.get_or_insert_with(MermaidRuntime::new);

Prevention

When it happens

Trigger: Only reachable if `MermaidRuntime::new()` panics (leaving the field never stored) or if the borrow/invariant around `&mut self` is violated by refactoring; normal call flow (first mermaid render request via `request_mermaid_render`) cannot trigger it.

Common situations: A refactor that moved or removed the `self.mermaid = Some(...)` assignment; `MermaidRuntime::new()` panicking during asset/worker initialization (see error 745's thread spawn); concurrent access bugs surfaced by unsafe code changes.

Related errors


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