astral-sh/ruff · error
unexpected annotation type: {annotation:?}
Error message
unexpected annotation type: {annotation:?} What it means
Defensive arm in the multiline-underline drawing code of the vendored renderer. The branch is entered only when matches! has already confirmed the annotation type is MultilineStart or MultilineEnd ('the beginning of a multiline span with its leftward moving line on the same line'), so the '_ => panic!' arm exists purely to satisfy exhaustiveness. Reaching it means the renderer's internal annotation classification became inconsistent — an internal bug in ruff_annotate_snippets rather than a misuse of the documented API.
Source
Thrown at crates/ruff_annotate_snippets/src/renderer/render.rs:1428
uline.underline,
uline.style,
);
}
if pos == 0
&& matches!(
annotation.annotation_type,
LineAnnotationType::MultilineStart(_) | LineAnnotationType::MultilineEnd(_)
)
{
// The beginning of a multiline span with its leftward moving line on the same line.
buffer.putc(
line_offset + 1,
(code_offset + annotation.start.display).saturating_sub(left),
match annotation.annotation_type {
LineAnnotationType::MultilineStart(_) => uline.top_right_flat,
LineAnnotationType::MultilineEnd(_) => uline.multiline_end_same_line,
_ => panic!("unexpected annotation type: {annotation:?}"),
},
uline.style,
);
} else if pos != 0
&& matches!(
annotation.annotation_type,
LineAnnotationType::MultilineStart(_) | LineAnnotationType::MultilineEnd(_)
)
{
// The beginning of a multiline span with its leftward moving line on another line,
// so we start going down first.
buffer.putc(
line_offset + 1,
(code_offset + annotation.start.display).saturating_sub(left),
match annotation.annotation_type {
LineAnnotationType::MultilineStart(_) => uline.multiline_start_down,
LineAnnotationType::MultilineEnd(_) => uline.multiline_end_up,
_ => panic!("unexpected annotation type: {annotation:?}"),View on GitHub (pinned to d1087a4b9e)
Solutions
- Minimize the failing case to source text plus span ranges in a ruff_annotate_snippets test and report it to the ruff repository — this arm is unreachable by design and needs a library fix.
- Pin to the last known-good ruff_annotate_snippets revision until the fix lands.
- As a local workaround, adjust the offending annotation (e.g. clamp the multiline span to a single line) so the multiline drawing path is not taken.
Defensive patterns
Strategy: try-catch
Validate before calling
fn spans_sane(source: &str, anns: &[Annotation<'_>]) -> bool {
let len = source.len();
anns.iter().all(|a| a.span.start <= a.span.end && a.span.end <= len + 1)
} Try / catch
let out = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
renderer.render(&report)
}))
.unwrap_or_else(|_| format!("{path}: {title}")); // degrade to a location-only line Prevention
- Pin and snapshot-test the vendored ruff_annotate_snippets revision.
- Derive annotation spans from one current source; avoid hand-built multiline ranges.
- When a multiline render panics, minimize to source + ranges and report upstream rather than papering over it.
When it happens
Trigger: Rendering a diagnostic with multiline spans in a combination that trips a classification bug (e.g. multiline markers landing at column 0 or start/end markers sharing a line); the panic fires while drawing the underline row of the snippet.
Common situations: New snapshot tests with unusual multiline spans; changes to the vendored ruff_annotate_snippets fork; diagnostics built from hand-constructed ranges instead of real files.
Related errors
- Expected a Title
- Annotation range `{bigger:?}` is beyond the end of buffer `{
- Patch span `{bigger:?}` is beyond the end of buffer `{source
- Expected a ty `File`, found a ruff `SourceFile`
- should be set because `extract_if` only yields elements with
AI-assisted analysis of astral-sh/ruff@d1087a4b9e (2026-08-20).
Data as JSON: /api/errors/de91ce95aa6853cc.
Report an issue: GitHub.