BoundaryML/baml · error

writing to a String cannot fail

Error message

writing to a String cannot fail

What it means

A panic from `write!(self.text, "{value}").expect("writing to a String cannot fail")` inside the `text()` builder method of the diagnostic message type. Formatting into a Rust `String` can only fail if the underlying formatter fails, which for `String` targets is essentially impossible; this expect converts an unrecoverable formatting error into a panic. In practice it panics only when the Display impl of the interpolated value panics or misbehaves, or if a gigantic formatted value exhausts memory during string growth.

Source

Thrown at baml_language/crates/baml_compiler_diagnostics/src/message.rs:66

                .map(|offset| content_start + offset)
            else {
                break;
            };
            if content_start < close {
                highlights.push(DiagnosticMessageHighlight {
                    start: u32::try_from(content_start).expect("diagnostic text exceeds 4 GiB"),
                    end: u32::try_from(close).expect("diagnostic text exceeds 4 GiB"),
                    kind: DiagnosticMessageKind::Code,
                });
            }
            cursor = close + 1;
        }
        Self { text, highlights }
    }

    #[must_use]
    pub fn text(mut self, value: impl fmt::Display) -> Self {
        write!(self.text, "{value}").expect("writing to a String cannot fail");
        self
    }

    #[must_use]
    pub fn identifier(self, value: impl fmt::Display, kind: DiagnosticIdentifierKind) -> Self {
        self.fragment(value, DiagnosticMessageKind::Identifier(kind))
    }

    #[must_use]
    pub fn type_expr(self, value: impl fmt::Display) -> Self {
        self.fragment(value, DiagnosticMessageKind::TypeExpression)
    }

    #[must_use]
    pub fn code(self, value: impl fmt::Display) -> Self {
        self.fragment(value, DiagnosticMessageKind::Code)
    }

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Inspect the `Display` implementation of the value passed to `.text()`; fix any panic/unwrap inside it.
  2. Shrink or truncate the value before formatting (e.g. format a summary or snippet, not the whole object/file).
  3. Avoid deeply recursive or unbounded Debug/Display output that can balloon the message string; cap the payload size.
  4. If memory pressure is the cause, reduce concurrent compiler work or stream diagnostics instead of buffering one huge message.

Example fix

// before
msg.text(raw_file_contents)
// after
msg.text(truncate(&raw_file_contents, 2048))
fn truncate(s: &str, max: usize) -> &str { match s.char_indices().nth(max) { Some((i, _)) => &s[..i], None => s } }
Defensive patterns

Strategy: type-guard

Validate before calling

fn safe_display(value: &impl fmt::Display) -> bool {
    // Display cannot be pre-run without side effects; instead bound the formatted size:
    true
}
// Guard: only pass bounded, trusted values into .text()
fn is_bounded(s: &str, max: usize) -> bool { s.len() <= max }

Type guard

fn is_panics_free_display<T: fmt::Display>(_: &T) -> bool { true }
// Prefer guarding the value's size before formatting:
fn guard_size(s: &str) -> bool { s.len() <= 64 * 1024 }

Try / catch

let msg = std::panic::catch_unwind(|| builder.text(value))
    .unwrap_or_else(|_| builder.text("<unformattable value>"));

Prevention

When it happens

Trigger: Calling `.text(value)` on the diagnostic builder where `value`'s `Display` implementation panics (e.g. it unwraps on invalid internal state) or where formatting a value larger than available memory forces an allocation failure in `String::push_str`.

Common situations: Passing a custom/newtype whose Display impl panics (unwrap on None, division by zero); passing a value that expands to terabytes (nested debug output); OOM conditions on memory-constrained machines while building large diagnostics.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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