---
title: "Typed errors and catch"
image: "https://hem.run/social/hem.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://hem.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Typed errors and catch

Under the Effect extension, `error` declarations emit `Data.TaggedError`, shape-compatible with the core emit, so `instanceof` and `_tag` work across both modes and plain-compiled modules exchange errors with effect-compiled ones directly. `raise` sends errors to the error channel instead of throwing on the stack, and `catch` attaches to **any effect-valued expression**, binding looser than `|>`:

```hem
let user = getUser(id) catch {
| UserNotFound(_) => anonymousUser
| DbError(e) => effect { Log.warn(e)!; raise ServiceDown }
}
```

Tag arms lower to `Effect.catchTags` (narrowing the error channel type), and `_` lowers to `Effect.catch`. Arm bodies are implicitly effect-positioned: a pure expression wraps in `Effect.succeed`, an effect passes through, and a block becomes a nested `effect { }`. A binding arm `e => …` lowers to `Effect.catch`; only tagged errors are catchable by name, and catch-arm guards are not supported. Arm syntax and propagation rules match §11, with one difference: under the extension `_` recovers the typed **failure** channel only. A `throw` inside an effect is a defect and bypasses `Effect.catch`, following Effect's native semantics.

Source: https://hem.run/tour/typed-errors-and-catch/index.mdx
