GALA-E0002 — Non-exhaustive match on a sealed type

What it means. A match expression on a sealed type omits one or more variants, or covers one only in part, and has no default (case _ =>) fallback. The compiler lists exactly which variants are missing.


Code that triggers it

package main

sealed type Color {
    case Red()
    case Green()
    case Blue()
}

func name(c Color) string = c match {
    case Red()   => "red"
    case Green() => "green"
    // missing: Blue
}

func main() {
    Println(name(Red()))
}

Compiler message

error[GALA-E0002]: non-exhaustive match: missing cases: Blue
  --> e0002.gala:10:5
   |
10 |     case Red()   => "red"
   |     ^^^^ add the missing variant cases, or add a `case _ => ...` defa…
   |
   = hint: add the missing variant cases, or add a `case _ => ...` default to cover them

The caret marks the start of the match arms; the header names the variants you left out.


How to fix it

Cover every variant explicitly:

func name(c Color) string = c match {
    case Red()   => "red"
    case Green() => "green"
    case Blue()  => "blue"
}

Or add a default when the remaining variants collapse to the same result:

func name(c Color) string = c match {
    case Red() => "red"
    case _     => "other"
}

A variant covered only in part

A variant counts as covered only when its cases match every value of its fields. Some(0) matches only one Some, and a case with an if guard covers nothing, since its guard may be false. The missing list then names the variant as Some(...):

package main

func describe(o Option[int]) string = o match {
    case Some(0) => "zero"
    case None()  => "none"
}

func main() {
    Println(describe(Some(3)))
}
error[GALA-E0002]: non-exhaustive match: missing cases: Some(...)
  --> main.gala:4:5
  |
4 |     case Some(0) => "zero"
  |     ^^^^ add the missing variant cases, or add a `case _ => ...` defa…
  |
  = hint: add the missing variant cases, or add a `case _ => ...` default to cover them

Cover the rest of the variant with a case that matches all of it, such as case Some(_) => "other". Nested patterns count together: Some(Some(_)), Some(None()) and None() cover every Option[Option[int]].

Why the rule exists

Sealed types exist so the compiler can verify you have thought about every variant. A silent fall-through would carry the same risk as a Go switch with a forgotten case. GALA therefore requires either full coverage or an explicit acknowledgement (case _ =>) that some variants are grouped.

This is the payoff of sealing a hierarchy: add a variant later, and every non-exhaustive match in the codebase becomes a compile error instead of a runtime surprise.