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 |>:
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.