BoundaryML/baml · error

colored diagnostics have a source highlighter

Error message

colored diagnostics have a source highlighter

What it means

miette_handler configures the graphical report handler; when color is enabled it requires a source-code syntax highlighter and panics with this message if the Option<DiagnosticHighlighter> is None. The invariant is: colored output always comes with a highlighter (callers like render_miette and render_diagnostics_with_highlighters supply one when color=true).

Source

Thrown at baml_language/crates/baml_compiler_diagnostics/src/render.rs:331

    severity: Severity,
) -> GraphicalReportHandler {
    let mut theme = if color {
        GraphicalTheme::unicode()
    } else {
        GraphicalTheme::unicode_nocolor()
    };
    if color {
        theme.styles.highlights = annotation_styles(severity);
    }
    let mut handler = GraphicalReportHandler::new_themed(theme)
        .with_links(false)
        .with_urls(false)
        .with_show_related_as_nested(true)
        .with_break_words(false)
        .with_context_lines(0);
    if color {
        handler = handler.with_syntax_highlighting(
            highlighter.expect("colored diagnostics have a source highlighter"),
        );
    } else {
        handler = handler.without_syntax_highlighting();
    }
    handler
}

fn render_miette_with_handler(
    diagnostic: &Diagnostic,
    sources: &HashMap<FileId, String>,
    file_paths: &HashMap<FileId, PathBuf>,
    handler: &GraphicalReportHandler,
    color: bool,
    show_error_codes: bool,
    message_highlighter: Option<&dyn DiagnosticMessageHighlighter>,
) -> Result<String, DiagnosticMessageHighlightError> {
    let diagnostic = build_rendered_diagnostic(
        diagnostic,

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Pass a DiagnosticHighlighter whenever color is enabled (the same value the standard render entry points use).
  2. Guard the call site: only request colored output when a highlighter is available, otherwise fall back to no-color.
  3. If you want color without semantic highlighting, change miette_handler to use a default syntax highlighting theme instead of expect().

Example fix

// before
if color {
    handler = handler.with_syntax_highlighting(
        highlighter.expect("colored diagnostics have a source highlighter"),
    );
}
// after
if color {
    match highlighter {
        Some(h) => handler = handler.with_syntax_highlighting(h),
        None => { color = false; handler = handler.without_syntax_highlighting(); }
    }
}
Defensive patterns

Strategy: validation

Validate before calling

if color && highlighter.is_none() {
    // disable color or supply a DiagnosticHighlighter before rendering
    color = false;
}

Type guard

fn highlighter_ready(color: bool, h: &Option<DiagnosticHighlighter>) -> bool {
    !color || h.is_some()
}

Try / catch

let out = std::panic::catch_unwind(|| render_diagnostic(&diag, &sources, &cfg, Some(highlighter)));
if out.is_err() { /* retry without color */ }

Prevention

When it happens

Trigger: Calling miette_handler (directly or through render_miette / render_diagnostics_with_highlighters) with color=true but highlighter=None — e.g. a code change that drops the highlighter argument or a call site that forgets to thread the user-configured highlighter through.

Common situations: Only when hacking on the crate: adding a new render entry point that enables color but forgets to pass the DiagnosticHighlighter, or a config path where theme/color is resolved to true without loading the highlighter.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/d0d427079a3b52a5. Report an issue: GitHub.