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

  1. 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.
  2. Pin to the last known-good ruff_annotate_snippets revision until the fix lands.
  3. 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

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


AI-assisted analysis of astral-sh/ruff@d1087a4b9e (2026-08-20). Data as JSON: /api/errors/de91ce95aa6853cc. Report an issue: GitHub.