Error
error declares error types. Errors are lightweight values: constructed uniformly with new, flowing along the fail channel; once consumed they are ordinary data — printable, reference-comparable, with a readable payload. This page covers the declaration surface of errors; for the complete story of throwing and consuming see Failure.
Declaration Forms
error NotFound(key: string); // shorthand: positional payload
error Boom(); // empty payload
error Bad(code: int, msg: string); // multiple fields- The shorthand form must carry a payload; bare
error Name;is illegal. - The full body form
error Name(key: int) { func Hint() -> string { ... } }can carry methods. - The generic error
error Bad<T>(value: T);is legal, and each instantiation is its own type (Bad<int>andBad<string>are different errors); constructor arguments can be inferred (new Bad(42)infersBad<int>). sealed error Name(...);forbids further inheritance.
Inheritance and the Payload Prefix
Errors inherit singly; the base error follows the colon. The derived payload must have the base payload as a prefix (same order, same names, same types; appending is allowed):
error NotFound(key: string);
error Wrapped(key: string, msg: string) : NotFound;
val w = new Wrapped("silver", "extra");
print(w.key, w.msg);silver extraw carries both of its own fields. A base-error arm catches derived values (write the base error name as a match / recover arm and read the payload at the base-declared prefix positions), and fail contracts override along the inheritance chain.
The errors Union
errors merges several errors into one name, used exclusively in fail clauses:
errors App = NotFound | Boom;
func Load(key: string) fail App -> int
{
if key == "gold"
{
return 7;
}
fail new NotFound(key);
}The union appears only in the fail clause position; it is not a value type, and using it as a parameter or variable type reports unknown type.
Construction-Point Origin: @site
Every error value automatically carries the construction point’s file:line:col, read through the hidden field @site:
val b = capture Load("silver");
match b
{
Success(v) => print("got", v),
Failure(e) => print("failed", e.key, e.@site is string),
}failed silver True@site takes no payload slot and does not participate in equality (error equality is reference comparison).
Discriminating Error Values
Error values support is type tests and as conversions, with inheritance-chain semantics: a derived value is its base error is True, the reverse is False:
func LoadWrap(key: string) fail Wrapped -> int
{
if key == "gold" { return 7; }
fail new Wrapped(key, "extra");
}
val e = recover capture LoadWrap("silver")
{
Success(x) => new NotFound("empty"),
Failure(err) => err,
};
print(e is NotFound, e is Wrapped);
if e is Wrapped
{
val wr = e as Wrapped;
print(wr?.msg);
}True True
extrae holds the derived error Wrapped: e is NotFound is True via the inheritance chain, and e is Wrapped is True by identity. The other way around, a plain NotFound tested with is Wrapped yields False.
Notes
- For discriminating error kinds, prefer match arms on the error name (which can destructure the payload at the same time);
is/assuit lightweight branches. See Failure. - Error equality is reference comparison.
