Skip to content
Source
Sign inSign up

cause.md

163 lines6.4 KB

Cause: Flattened Structure

In v3, Cause<E> was a recursive tree with six variants:

Empty | Fail<E> | Die | Interrupt | Sequential<E> | Parallel<E>

The Sequential and Parallel variants composed causes into a tree to represent errors from finalizers or concurrent operations.

In v4, Cause<E> has been flattened to a simple wrapper around an array of Reason values:

interface Cause<E> {
  readonly reasons: ReadonlyArray<Reason<E>>
}

type Reason<E> = Fail<E> | Die | Interrupt

There are only three reason variants — Fail, Die, and Interrupt. The Empty, Sequential, and Parallel variants have been removed. An empty cause is represented by an empty reasons array. Multiple failures (from concurrent or sequential composition) are collected into a flat array.

Accessing Reasons

v3 — pattern match on the recursive tree structure:

import { Cause } from "effect"

const handle = (cause: Cause.Cause<string>) => {
  switch (cause._tag) {
    case "Fail":
      return cause.error
    case "Die":
      return cause.defect
    case "Empty":
      return undefined
    case "Sequential":
      return handle(cause.left)
    case "Parallel":
      return handle(cause.left)
    case "Interrupt":
      return cause.fiberId
  }
}

v4 — iterate over the flat reasons array:

import { Cause } from "effect"

const handle = (cause: Cause.Cause<string>) => {
  for (const reason of cause.reasons) {
    switch (reason._tag) {
      case "Fail":
        return reason.error
      case "Die":
        return reason.defect
      case "Interrupt":
        return reason.fiberId
    }
  }
}

Reason Guards

The v3 type-level guards (isFailType, isDieType, isInterruptType, etc.) have been replaced by reason-level guards:

v3v4
Cause.isEmptyType(cause)cause.reasons.length === 0
Cause.isFailType(cause)Cause.isFailReason(reason)
Cause.isDieType(cause)Cause.isDieReason(reason)
Cause.isInterruptType(cause)Cause.isInterruptReason(reason)
Cause.isSequentialType(cause)Removed
Cause.isParallelType(cause)Removed

Cause-Level Predicates

v3v4
Cause.isFailure(cause)Cause.hasFails(cause)
Cause.isDie(cause)Cause.hasDies(cause)
Cause.isInterrupted(cause)Cause.hasInterrupts(cause)
Cause.isInterruptedOnly(cause)Cause.hasInterruptsOnly(cause)

Constructors

v3v4
Cause.emptyCause.empty
Cause.fail(error)Cause.fail(error)
Cause.die(defect)Cause.die(defect)
Cause.interrupt(fiberId)Cause.interrupt(fiberId)
Cause.sequential(left, right)Cause.combine(left, right)
Cause.parallel(left, right)Cause.combine(left, right)

In v4, Cause.combine concatenates the reasons arrays of two causes. The distinction between sequential and parallel composition is no longer represented in the data structure.

Extractors

v3v4
Cause.failureOption(cause)Cause.findErrorOption(cause)
Cause.failureOrCause(cause)Cause.findError(cause)
Cause.dieOption(cause)Cause.findDefect(cause)
Cause.interruptOption(cause)Cause.findInterrupt(cause)
Cause.failures(cause)cause.reasons.filter(Cause.isFailReason)
Cause.defects(cause)cause.reasons.filter(Cause.isDieReason)
Cause.interruptors(cause)Cause.interruptors(cause)

Note: findError and findDefect return Result.Result instead of Option. Use findErrorOption for the Option-based variant.

Error Classes

All *Exception classes have been renamed to *Error:

v3v4
Cause.NoSuchElementExceptionCause.NoSuchElementError
Cause.TimeoutExceptionCause.TimeoutError
Cause.IllegalArgumentExceptionCause.IllegalArgumentError
Cause.ExceededCapacityExceptionCause.ExceededCapacityError
Cause.UnknownExceptionCause.UnknownError
Cause.RuntimeExceptionRemoved
Cause.InterruptedExceptionRemoved
Cause.InvalidPubSubCapacityExceptionRemoved

The corresponding guards follow the same pattern:

v3v4
Cause.isNoSuchElementException(u)Cause.isNoSuchElementError(u)
Cause.isTimeoutException(u)Cause.isTimeoutError(u)
Cause.isIllegalArgumentException(u)Cause.isIllegalArgumentError(u)
Cause.isExceededCapacityException(u)Cause.isExceededCapacityError(u)
Cause.isUnknownException(u)Cause.isUnknownError(u)

New in v4

  • Cause.fromReasons(reasons) — construct a Cause from an array of Reason values.
  • Cause.makeFailReason(error), Cause.makeDieReason(defect), Cause.makeInterruptReason(fiberId) — construct individual Reason values.
  • Cause.annotate(cause, annotations) — attach annotations to a Cause.
  • Cause.findFail(cause), Cause.findDie(cause), Cause.findInterrupt(cause) — extract specific reason types using the Result module.
  • Cause.filterInterruptors(cause) — extract interrupting fiber IDs as a Result.
  • Cause.Done — a graceful completion signal for queues and streams.