gleam-lang/gleam · error

`panic` expression evaluated.

Error message

`panic` expression evaluated.

What it means

Gleam's `panic` keyword is compiled to JavaScript as a `throw` of a `GleamError` built by the generated `throwMakeError(...)` call (compiler-core/src/javascript/expression.rs:2584-2634). When the `panic` expression has no custom label (`panic as "..."`), the default message is exactly "`panic` expression evaluated.". The thrown error also carries the originating .gleam module, line number, and function name, so it pinpoints which panic site was reached. This is the designed runtime abort for Gleam programs compiled to JavaScript, not a compiler bug.

Source

Thrown at compiler-core/src/javascript/expression.rs:2584

        let message = match message {
            Some(m) => self.not_in_tail_position(None, |this| this.wrap_expression(arena, m)),
            None => string(
                arena,
                "`todo` expression evaluated. This code has not yet been implemented.",
            ),
        };
        self.throw_error(arena, "todo", &message, *location, vec![])
    }

    fn panic(
        &mut self,
        arena: &'doc DocumentArena<'a, 'doc>,
        location: &'a SrcSpan,
        message: Option<&'a TypedExpr>,
    ) -> Document<'a, 'doc> {
        let message = match message {
            Some(m) => self.not_in_tail_position(None, |this| this.wrap_expression(arena, m)),
            None => string(arena, "`panic` expression evaluated."),
        };
        self.throw_error(arena, "panic", &message, *location, vec![])
    }

    pub(crate) fn throw_error<Fields>(
        &mut self,
        arena: &'doc DocumentArena<'a, 'doc>,
        error_name: &'a str,
        message: &Document<'a, 'doc>,
        location: SrcSpan,
        fields: Fields,
    ) -> Document<'a, 'doc>
    where
        Fields: IntoIterator<Item = (&'a str, Document<'a, 'doc>)>,
    {
        self.tracker.make_error_used = true;
        let module = self.module_name.clone().to_doc(arena).surround(
            arena,

View on GitHub (pinned to 7e623aa83d)

Solutions

  1. Read the thrown error's module/line/function fields (e.g. module `my_module`, line 42, function `head`) and open that .gleam file — that is the exact panic site
  2. Replace the panicking branch with real handling: return `Result(t, e)` or handle the case instead of aborting
  3. If the abort is intentional, add a label `panic as "descriptive message"` so the next failure names the cause
  4. If the panic is inside a dependency, check the call's preconditions (non-empty list, present key, valid range) and validate before calling

Example fix

// before (src/my_module.gleam)
pub fn head(list: List(a)) -> a {
  case list {
    [x, ..] -> x
    [] -> panic
  }
}

// after
pub fn head(list: List(a)) -> Result(a, Nil) {
  case list {
    [x, ..] -> Ok(x)
    [] -> Error(Nil)
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Gleam: give callers a checkable value instead of an abort
pub fn head(list: List(a)) -> Result(a, Nil) {
  case list {
    [x, ..] -> Ok(x)
    [] -> Error(Nil)
  }
}

Try / catch

// JavaScript host around generated Gleam .mjs
import * as myModule from "./build/dev/javascript/my_pkg/my_module.mjs";
import { GleamError } from "./build/dev/javascript/my_pkg/gleam.mjs";

try {
  myModule.doThing();
} catch (e) {
  if (e instanceof GleamError) {
    // payload identifies the panic site (module, line, function)
    console.error("Gleam panic reached:", e);
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: Executing generated JavaScript (via `gleam run` on the JavaScript target, or importing the emitted .mjs from Node) in a way that reaches a message-less `panic`: a bare `panic` in a function body, a `case` branch ending in `panic`, or a dependency helper that panics on the input you passed (e.g. an 'impossible' empty-input branch).

Common situations: Scaffolding code where `panic` was left as a placeholder; a case branch believed unreachable that is in fact reachable at runtime; unexpected inputs such as an empty list or a missing key reaching a panicking helper inside a published Hex package.

Related errors


AI-assisted analysis of gleam-lang/gleam@7e623aa83d (2026-08-17). Data as JSON: /api/errors/b046cfda31bb8b5f. Report an issue: GitHub.