Skip to main content
Version: 0.10.0

Metel Error Code Reference

All Metel errors carry a code. Codes are prefixed by phase:

PrefixPhase
PParse — invalid source text
TType — type-checker rejection
RRuntime — error during execution
IInternal — bug in the interpreter (please report)

Parse errors (P)

P0001 — Syntax error

The source text does not match the Metel grammar.

[P0001] parse error in main.mtl at 12..18 (`let x = ;`): expected expression

Fix: correct the syntax at the indicated position.

P0002 — Invalid integer literal

An integer literal is out of range for i64 (−9,223,372,036,854,775,808 to 9,223,372,036,854,775,807).

[P0002] parse error in main.mtl at 4..24: integer literal '99999999999999999999' is out of range for i64

Fix: use a value that fits in i64, or split the computation.

P0003 — Invalid float literal

A float literal cannot be represented as an f64.

[P0003] parse error in main.mtl at 4..12: invalid float literal '1e9999'

Fix: use a value within the f64 range (~±1.8 × 10³⁰⁸).


Type errors (T)

T0001 — Type mismatch

Two types that must be equal are not.

[T0001] type error in main.mtl at 10..20: expected i64, got boolean

Fix: ensure the expression produces the expected type. Add an explicit cast if widening (e.g. x as f64).

T0002 — Annotation required

The type checker cannot infer a type without an explicit annotation.

[T0002] type error in main.mtl at 5..10: cannot infer type of `x`; add a type annotation

Fix: annotate the binding: let x: i64 = ....

T0003 — Undefined name

A name is used but not defined in the current scope.

[T0003] type error in main.mtl at 8..12: undefined name `foo`

Fix: define the variable or function before use, or correct the spelling.

T0004 — Arity mismatch

A function is called with the wrong number of arguments.

[T0004] type error in main.mtl at 5..20: expected 2 arguments, got 3

Fix: pass the exact number of arguments the function declares.

T0005 — Invalid operand types

A binary operator is applied to types it does not support.

[T0005] type error in main.mtl at 6..13: operator `+` cannot be applied to boolean and i64

Fix: use compatible types, or cast one operand.

T0006 — Assignment to immutable binding

A write operation targets a let binding. This covers three forms:

  • Direct reassignment: x = newValue
  • Field assignment through an immutable binding: point.x = 1
  • Taking a mutable reference to an immutable binding: &var x
[T0006] type error in main.mtl at 3..12: `x` is immutable; use `var x` to allow reassignment

Fix: change the binding declaration to var.

T0007 — Invalid cast

A as cast between incompatible types.

[T0007] type error in main.mtl at 5..15: cannot cast boolean to i64

Fix: only cast between numeric types (i64 as f64). Use an explicit conversion function for other types.

T0008 — Non-exhaustive match

A match expression does not cover all possible values of the scrutinee type.

[T0008] type error in main.mtl at 2..30: match on Colour is non-exhaustive; missing variant `Blue`

Fix: add the missing arms, or add a wildcard arm _ => ....

T0012 — Aspect bound not satisfied

A generic type parameter's bound is not satisfied by the concrete type at the call site or construction site. Covers both directions: a positive bound (T: Aspect) requires an implementation that isn't reachable, or a negative bound (T: !Aspect, RFC-0072) is violated because the concrete type does implement the aspect. Also covers a conditional extend block's own where-clause bounds (RFC-0036) failing at a use site — the same check as an ordinary function bound, just reached through an implementation block's condition instead of a function's generic parameter.

[T0012] type error in main.mtl at 5..15: `i64` does not implement `Display` (required by `show`)
[T0012] type error in main.mtl at 8..20: `Handle` implements `Drop`; `!Drop` bound not satisfied (required by `move_out`)
[T0012] type error in main.mtl at 3..12: `Pair<i64, SomeNonPrintable>` does not implement `Printable`, because `SomeNonPrintable` does not implement `Printable`

A type satisfying T: Copy automatically satisfies T: !Drop (RFC-0072 §2.3) even though it implements Drop — this is a narrow, Copy/Drop-specific exception, not a general rule.

Fix: implement the required aspect for the type, or (for a negative bound) remove the conflicting positive implementation.

T0013 — Ambiguous aspect method/associated-type resolution

Two different aspects define the same method name on the same receiver type, so a call like value.method() does not have a unique static target — or (RFC-0082 §3a) two different aspects bound on the same generic type parameter both declare an associated type of the same name, so a bare projection like T::AssocName doesn't have a unique target either.

[T0013] type error in main.mtl at 12..20: ambiguous aspect method `label` on type `S`: both `A` and `B` provide this method
[T0013] type error in main.mtl at 8..16: ambiguous associated type `Target`: multiple aspects declare it: Deref, Convert

Fix (method case): rename one of the methods, remove one of the conflicting impls, or change the design so the receiver type does not expose two indistinguishable aspect methods.

Fix (associated-type case): bind the associated type to a fresh type parameter via an equality-constrained bound instead of projecting it directly — e.g. fun f<T: Deref<Target = U> + Convert, U>(x: &T) -> U — which resolves unambiguously since U is an ordinary type parameter, not a projection.

T0014 — Orphan implementation

An extend Type: Aspect block where neither Aspect nor Type's outermost type constructor is declared in the current module (or std::core, for built-ins).

[T0014] type error in main.mtl at 1..40: orphan implementation: neither `Display` nor `i64` is local to this module

Fix: move the extend block into the module that declares the aspect or the type, or (for two foreign types) into std::core if this is genuinely a standard-library concern.

T0015 — Conflicting implementation

Two implementations of the same aspect cover the same concrete type — either two identical extend blocks, or a positive and a negative impl (see Negative Impls in the declarations reference) for the same concrete type.

[T0015] type error in main.mtl at 1..40: conflicting implementation: `Display` is already implemented for `List<i64>` at 10..30

Fix: remove the duplicate extend block, or narrow one block's type arguments so the two no longer overlap.

T0016 — Non-diverging -> ! function

A function declared -> ! (RFC-0078) contains a reachable path that doesn't diverge — most commonly an ordinary return <expr> where <expr> isn't itself !-typed. A -> ! function promises never to return; the compiler verifies every control-flow path ends in a diverging expression (a panic, a loop with no reachable break, or a return/tail expression whose own value is already !-typed).

[T0016] type error in main.mtl at 1..40: function `bad` is declared `-> !` but does not diverge on all paths

Fix: make every path genuinely diverge (panic(msg), loop { }, or a recursive/other !-returning call), or drop the -> ! annotation if the function is meant to return normally.

T0017 — Missing associated type definition

An extend Type: Aspect block omits a type Name = ConcreteType; definition for an associated type the aspect declares (RFC-0082 §2). Every implementation of an aspect with associated types must define all of them.

[T0017] type error in main.mtl at 1..40: `IntBox` is missing associated type `Item` required by aspect `Container`

Fix: add the missing type Item = ConcreteType; definition to the extend block.


Runtime errors (R)

R0001 — No main function defined

Execution requires a main function but none was found.

[R0001] runtime error in main.mtl at 0..0: no main() function defined

Fix: add fun main() { ... } to your program.

R0002 — main is not a valid entry point

main exists but is generic or is not a function.

[R0002] runtime error in main.mtl at 0..0: main() is generic — not supported in v0.1

Fix: main must be a concrete, non-generic function with no parameters.

R0003 — Undefined variable at runtime

A variable name is not found in the current environment. This can occur when a variable is used before it is defined in a branch that the type-checker did not flag.

[R0003] runtime error in main.mtl at 10..15: undefined variable `x`

R0004 — Index out of bounds

An array index is negative or ≥ the array length.

[R0004] runtime error in main.mtl at 5..10: index 5 out of bounds (len 3)

Fix: check that the index is within 0..array.len() before access.

R0005 — Tuple index out of bounds

A tuple element is accessed by an index that does not exist.

[R0005] runtime error in main.mtl at 5..10: tuple index 3 out of bounds

Fix: tuple indices are fixed at compile time; verify the index against the tuple's declared length.

R0006 — Non-exhaustive match at runtime

A match expression reached its end without any arm matching. This indicates a pattern that the type checker approved as exhaustive but that is not, which is a known limitation.

[R0006] runtime error in main.mtl at 2..30: match: no arm matched scrutinee

R0007 — Arithmetic error

Integer division or remainder by zero.

[R0007] runtime error in main.mtl at 8..13: division by zero

Fix: guard with a zero check before dividing.

R0008 — Field not found

A struct or enum value does not have the accessed field.

[R0008] runtime error in main.mtl at 5..12: no field `colour` on value

Fix: check the field name against the type definition.

R0009 — Method not found

A method call cannot be resolved for the receiver type.

[R0009] runtime error in main.mtl at 5..20: no method `draw` on `Circle`

Fix: define the method in an extend block for the type.

R0010 — Call on non-callable value

A call expression (f(...)) is applied to a value that is not a function or closure.

[R0010] runtime error in main.mtl at 3..8: call: expected a closure or builtin

R0011 — Invalid for-in iterator

A for x in expr loop where expr does not evaluate to an Array or Range.

[R0011] runtime error in main.mtl at 1..20: for-in: expected Array or Range

Fix: ensure the iterable is an array literal, a range (a..b), or a variable of those types.

R0012 — Error propagation on non-Result value

The ? operator is applied to a value that is not a Result.

[R0012] runtime error in main.mtl at 5..10: ?: expected a Result value

Fix: only use ? on expressions whose type is Result[T, E].

Note: this misuse is actually caught statically. ? constrains its operand's type to Result<T, E> during type inference (infer_propagate_error), so a non-Result operand is rejected as a T0001 type mismatch before the program ever runs. R0012 does not appear in the interpreter's RuntimeErrorCode enum today and is unreachable in practice — kept here for the code number, not because the described runtime error can currently occur. (Found while investigating issue #232; not fixed as part of it, since removing a documented code is a separate decision from the yolo/conversion-method work that issue tracked.)

R0013 — Assertion failed

assert(cond) or assert(cond, msg) is called with cond evaluating to false. The panic message is the fixed string "assertion failed" for the one-argument form, or the caller-supplied msg for the two-argument form.

[R0013] runtime error in main.mtl at 5..10: assertion failed

Fix: this is not a bug in the interpreter — it means the asserted condition was actually false at runtime. Fix the condition, or the code that led to it.

R0014 — Unwrap on None/Err

.yolo() is called on a Perhaps<T> that is None, or a Result<T, E> that is Err. For Result, the panic message includes the Err value's debug representation.

[R0014] runtime error in main.mtl at 5..10: called `.yolo()` on a `None` value
[R0014] runtime error in main.mtl at 5..10: called `.yolo()` on an `Err` value: "not found"

Fix: this is not a bug in the interpreter — .yolo() is meant only for cases where None/Err represents a logic error that should never occur in correct code. Use match, .unwrap_or, .unwrap_or_else, or (for Result) ? to handle the expected case instead.

R0015 — Explicit panic

panic(msg) (RFC-0078) is called. Always panics unconditionally with msg.

[R0015] runtime error in main.mtl at 5..10: boom

Fix: this is not a bug in the interpreter — panic is meant for logic errors that should never occur in correct code. Handle the expected case with ordinary control flow instead of reaching the panic call.


Internal errors (I)

I0001 — Internal interpreter error

The interpreter reached an impossible state. This is a bug in the interpreter — the typechecker should have caught it before execution.

[I0001] internal error: binop: unsupported operand types (typechecker should have caught this)

What to do: please file a bug report at the Metel issue tracker with the source program that triggered this error.

I0002 — Not implemented

The program uses a language feature that is not yet supported in this version of the interpreter.

[I0002] internal error: generic functions are not supported in v0.1

What to do: check the changelog for the current supported feature set and the release plan for the planned implementation milestone.