Hmbown/CodeWhale · error

flat cache populated above

Error message

flat cache populated above

What it means

flattened() recomputes the flattened transcript when the FlatKey (generation/width/mode/options) is stale, stores it in flat_cache, and then borrows it. The expect fires only if the cache was not populated by the preceding stale-check block — i.e. a refactor moved or skipped the store step — since the very code above guarantees a fresh entry exists.

Source

Thrown at crates/tui/src/tui/live_transcript.rs:283

    /// render options — all of which are in `FlatKey`.
    fn flattened(&self, width: u16) -> std::cell::Ref<'_, FlattenedTranscript> {
        let key = FlatKey {
            generation: self.snapshots_generation.get(),
            width: width.max(1),
            mode: self.mode,
            options: self.options,
        };
        {
            let mut cache = self.flat_cache.borrow_mut();
            let stale = cache.as_ref().is_none_or(|cached| cached.key != key);
            if stale {
                let flat = self.flatten(key.width);
                self.flattens.set(self.flattens.get() + 1);
                *cache = Some(FlatCache { key, flat });
            }
        }
        std::cell::Ref::map(self.flat_cache.borrow(), |cache| {
            &cache.as_ref().expect("flat cache populated above").flat
        })
    }

    fn flatten(&self, width: u16) -> FlattenedTranscript {
        let width = width.max(1);
        let mut out: Vec<Line<'static>> = Vec::new();
        let mut out_links: Vec<Vec<crate::tui::osc8::LineLink>> = Vec::new();
        let mut highlighted_range = None;

        // Pre-compute which cell index (in `self.snapshots`) is the one
        // the user has selected via Esc-Esc. We walk snapshots backwards
        // counting User cells; the snapshot index whose count matches
        // `selected_idx + 1` is the highlighted one.
        let highlighted_cell_idx: Option<usize> = match self.mode {
            Mode::BacktrackPreview { selected_idx } => {
                let mut count = 0usize;
                let mut hit = None;
                for (idx, snap) in self.snapshots.iter().enumerate().rev() {

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Keep the borrow_mut store and the Ref borrow inside flattened() so no caller can observe an empty cache
  2. Invalidate by bumping snapshots_generation rather than clearing flat_cache directly
  3. If RefCell borrow conflicts arise, restructure rather than leaving the cache empty
Defensive patterns

Strategy: type-guard

When it happens

Trigger: Thrown at crates/tui/src/tui/live_transcript.rs:283 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/28dd09aac7975139. Report an issue: GitHub.