zed-industries/zed · error
invalid display row {}
Error message
invalid display row {} What it means
FoldMapSnapshot::row_infos(start_row) iterates fold rows starting at a display row; it panics with 'invalid display row {}' when start_row exceeds the snapshot's total row count (transforms summary output lines). Note the check is `>`, so start_row equal to the row count is legal (empty iterator at the end); anything beyond is invalid.
Source
Thrown at crates/editor/src/display_map/fold_map.rs:829
pub fn len(&self) -> FoldOffset {
FoldOffset(self.transforms.summary().output.len)
}
#[ztracing::instrument(skip_all)]
pub fn line_len(&self, row: u32) -> u32 {
let line_start = FoldPoint::new(row, 0).to_offset(self).0;
let line_end = if row >= self.max_point().row() {
self.len().0
} else {
FoldPoint::new(row + 1, 0).to_offset(self).0 - 1
};
(line_end - line_start) as u32
}
#[ztracing::instrument(skip_all)]
pub fn row_infos(&self, start_row: u32) -> FoldRows<'_> {
if start_row > self.transforms.summary().output.lines.row {
panic!("invalid display row {}", start_row);
}
let fold_point = FoldPoint::new(start_row, 0);
let mut cursor = self
.transforms
.cursor::<Dimensions<FoldPoint, InlayPoint>>(());
cursor.seek(&fold_point, Bias::Left);
let overshoot = fold_point.0 - cursor.start().0.0;
let inlay_point = InlayPoint(cursor.start().1.0 + overshoot);
let input_rows = self.inlay_snapshot.row_infos(inlay_point.row());
FoldRows {
fold_point,
input_rows,
cursor,
}
}View on GitHub (pinned to f4178619ac)
Solutions
- Derive start_row from the same snapshot you call row_infos on
- Clamp before calling: start_row = start_row.min(snapshot.max_point().row())
- If triggered inside Zed with no custom code, report the panic with the document/edit history — it indicates an internal invariant break
Example fix
// before let infos = fold_snapshot.row_infos(start_row); // possibly > row count // after let max_row = fold_snapshot.max_point().row(); let infos = fold_snapshot.row_infos(start_row.min(max_row));
Defensive patterns
Strategy: validation
Validate before calling
let max_row = fold_snapshot.max_point().row(); let start = start_row.min(max_row + 1); // row == count is allowed (empty tail) let infos = fold_snapshot.row_infos(start);
Type guard
fn fold_row_in_range(snapshot: &FoldSnapshot, row: u32) -> bool {
row <= snapshot.transforms_row_count() // i.e. summary().output.lines.row
} Prevention
- Derive iteration bounds from the same fold snapshot being iterated
- Clamp start rows after any await/refresh point where the snapshot may have changed
- Report internal occurrences upstream with the document state that triggered them
When it happens
Trigger: Calling row_infos (or editor APIs that delegate to it, like display_map row iteration) with a start row greater than the number of display rows — e.g. a row taken from a stale FoldSnapshot after folds or edits changed, or an unclamped loop bound from another snapshot.
Common situations: Rows cached from an earlier render pass reused after document edits; multi-snapshot code mixing buffer rows with display rows; internal regressions after fold changes.
Related errors
- row out of range
- blocking sender returned without value
- anchor's path was never added to multibuffer
- byte index {} is out of bounds of rope (length: {})
- {self:?} is not a named SearchOption
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/006a255189707728.
Report an issue: GitHub.