# Exceptions and cleanup

> Raise and rescue errors, run cleanup with ensure, and understand retry.

Canonical: https://alice-lang.org/documentation/language/exceptions/

[Documentation index](https://alice-lang.org/documentation/llms.txt) · [Complete book](https://alice-lang.org/llms-full.txt)

## Raise and rescue

Use an exception for a failure that interrupts normal execution. A typed rescue binds the exception object so you can inspect its .NET members.

```alice
def positive(n : Int32) : Int32
  raise "expected a positive number" if n <= 0
  n
end
begin
  puts positive(0)
rescue e : Exception
  puts e.Message
ensure
  puts "finished"
end
```

Expected output:

```text
expected a positive number
finished
```

[Edit and run in the Alice playground](https://playground.alice-lang.org/#code=u.ZGVmIHBvc2l0aXZlKG4gOiBJbnQzMikgOiBJbnQzMgogIHJhaXNlICJleHBlY3RlZCBhIHBvc2l0aXZlIG51bWJlciIgaWYgbiA8PSAwCiAgbgplbmQKYmVnaW4KICBwdXRzIHBvc2l0aXZlKDApCnJlc2N1ZSBlIDogRXhjZXB0aW9uCiAgcHV0cyBlLk1lc3NhZ2UKZW5zdXJlCiAgcHV0cyAiZmluaXNoZWQiCmVuZA)

`raise "message"` creates an error with that message. The guard exits the normal path; `rescue e : Exception` handles the failure. `e.Message` keeps .NET's member spelling.

## Ensure cleanup

`ensure` runs when leaving the protected block, including when an error occurred. Put resource cleanup there when a resource cannot be kept inside a simpler lifetime helper.

```alice
stream = System.IO.MemoryStream.new
begin
  stream.WriteByte(42)
  puts stream.Length
ensure
  stream.Dispose()
end
```

Handle the specific error types your application can recover from. Catching every exception and returning a default can hide a broken assumption.

## Retry

`retry` inside a rescue re-runs the `begin` body. Bound the number of attempts and ensure repeating the operation is safe. File writes, network calls, or charges may have happened before an exception; retry does not roll back those effects.

## Compile errors are different

A type mismatch, invalid syntax, nil dereference warning, immutable reassignment, or rejected concurrent write is a compilation failure. It cannot be caught by a runtime rescue because the program does not start. Read [diagnostics](https://alice-lang.org/documentation/reference/diagnostics.md) to fix those errors.

Use [enum variants](https://alice-lang.org/documentation/language/pattern-matching.md) for expected domain alternatives when callers should explicitly handle each outcome.

## Continue reading

- Previous: [Enums and pattern matching](https://alice-lang.org/documentation/language/pattern-matching.md)
- Next: [Dynamic features and DSLs](https://alice-lang.org/documentation/language/dynamic.md)
