<!-- nytrix-doc: {"audience":"user","featured":false,"group":"spec","order":180,"summary":"Recoverable results, compiler diagnostics, failure categories, and error propagation."} -->
Errors
Errors use assertions, panics, recoverable result values, and compiler
diagnostics.
Assertions
use std.core
def condition = true
def actual = [1, 2]
def expected = [1, 2]
assert(condition, "behavior")
assert_eq(actual, expected, "behavior")
Assertions fail the current execution with the supplied message. Assertion
messages name the behavior being checked.
Panic
use std.core
try {
panic("message")
} catch err {
assert_eq(repr(err), "\"message\"", "panic message")
}
panic aborts the current execution path. It is for unrecoverable states.
The abort is catchable by try/catch on the language/runtime path.
Choosing the failure form
| Condition | Form |
| Programmer error, impossible state, or invalid index/receiver | panic or assert |
| Recoverable operation whose caller can handle failure | Structured Result value |
| Language-level invalid source | Compiler diagnostic |
| Boundary worth a machine-readable code | Structured error with error_kind |
A panic aborts the current execution path and is catchable by try/catch.
A Result value flows through ordinary data. Prefer the recoverable form when
the caller has a real fallback, and panic when continuing would be wrong.
Structured errors
use std.core
use std.core.error
def e = exception(ERR_DIV_ZERO, "division by zero")
def w = warning(WARN_RUNTIME, "slow fallback")
assert_eq(error_kind(e), ERR_DIV_ZERO, "error kind")
assert_eq(error_message(e), "division by zero", "error message")
assert(is_error(e, ERR_DIV_ZERO), "error match")
assert_eq(error_kind(w), WARN_RUNTIME, "warning kind")
Structured errors and warnings are ordinary values with a kind and message.
Runtime panics produced by checked operations, such as division by zero or
invalid receiver/index access, can be captured by try/catch.
Error conventions
Use structured errors for recoverable library operations and diagnostics for
language failures. Keep messages compact and practical.
Recommended recoverable shape:
{"ok": false, "code": "invalid_graph", "message": "cycle at node 7", "at": 7}
Recommended success shape when a tagged result is useful:
{"ok": true, "value": result}
Rules:
- Preserve the original failing location.
- Report one primary cause before dependent failures.
- Include a stable machine-readable code where tooling consumes the error.
- Do not convert programmer errors into silent defaults.
- Use a deliberate fallback only when the public API promises one.
- Log degradation once, not every frame or iteration.
Recoverable results
Standard-library APIs can return Result values for recoverable failure.
Callers inspect the success/error shape before using the payload when
compile-time type checking requires refinement.
use std.core
def r = ok(42)
def e = err("missing")
assert(is_ok(r), "ok result")
assert(is_err(e), "err result")
assert_eq(unwrap(r), 42, "unwrap")
assert_eq(unwrap_or(e, 0), 0, "fallback")
Use ok(value) for success and err(value) for failure. is_ok, is_err,
unwrap, and unwrap_or provide the common checks. Match arms can destructure
ok(v) and err(e) when typed result refinement matters.
Diagnostics
Diagnostics identify source location, severity, and message. Compact
diagnostics collect a dense error set. Rich diagnostics print wider source
context.
ny --diag-compact --collect-errors file.ny
ny --diag-rich file.ny
Common compile-time failures
| Failure | Meaning |
| Undefined symbol | Missing import, wrong export name, or out-of-scope binding. |
| Unavailable receiver method | Receiver form is not available for that value/API. |
| Type-check failure | Dynamic shape was not refined enough. |
| Ownership failure | A move, borrow, release, return, or contract violates --borrow-check. |
| Compile-time proof failure | assert_compile, range proof, or index proof could not be proven. |
| Safe-mode raw memory failure | A raw pointer access lacks a proven in-bounds byte range. |
| Native boundary failure | Pointer, handle, layout, or ABI shape is wrong. |
| Parser failure | Source spelling is not a valid syntax form. |
Diagnostic quality
Diagnostics should always:
- Preserve the original failing source location.
- Report one primary cause before dependent failures.
- Include a stable machine-readable code where tooling consumes the error.
- Never convert programmer errors into silent defaults.
- Use a deliberate fallback only when the public API promises one.
- Log degradation once, not every frame or iteration.
Related
- Types for compile-time type rules.
- Syntax for parser-level forms.
- Troubleshooting for debugging workflow and fixes by symptom.