- Mark `fn` functions that can fail with `raises` in the signature (e.g., `fn parse(s: String) raises -> Int`) — the compiler enforces that callers handle the error.
- Use `try`/`except` blocks in `def` functions and propagate errors from `fn` functions by wrapping calls in `try` — never silently swallow exceptions.
- Prefer returning an `Optional[T]` from `fn` functions for expected-absent values rather than raising for control flow.
- Use `Error("message")` to construct error values; prefer descriptive messages that include the invalid value and the expected constraint.
- In `fn` contexts, handle all code paths explicitly — `fn` functions without `raises` must not call any function marked `raises` without a `try` block.
- Avoid using `except` as a broad catch-all; match specific error types when multiple exception kinds are possible.
- Return early with a raised error on invalid input at the top of a function — guard clauses keep the happy path un-indented.