Skip to content

Sandboxing

Errors are an inevitable part of programming, and they can arise from various sources like failures, defects, fiber interruptions, or combinations of these. This guide explains how to use the Effect.sandbox function to isolate and understand the causes of errors in your Effect-based code.

The Effect.sandbox function allows you to encapsulate all the potential causes of an error in an effect. It exposes the full cause of an effect, whether it’s due to a failure, defect, fiber interruption, or a combination of these factors.

In simple terms, it takes an effect Effect<A, E, R> and transforms it into an effect Effect<A, Cause<E>, R> where the error channel now contains a detailed cause of the error.

Syntax

Effect<A, E, R> -> Effect<A, Cause<E>, R>

By using the Effect.sandbox function, you gain access to the underlying causes of exceptional effects. These causes are represented as a type of Cause<E> and are available in the error channel of the Effect data type.

Once you have exposed the causes, you can utilize standard error-handling operators like Effect.catchAll and Effect.catchTags to handle errors more effectively. These operators allow you to respond to specific error conditions.

If needed, we can undo the sandboxing operation with Effect.unsandbox.

Example (Handling Different Error Causes)

1
import {
import Effect
Effect
,
import Console
Console
} from "effect"
2
3
// ┌─── Effect<string, Error, never>
4
// ▼
5
const
const task: Effect.Effect<string, Error, never>
task
=
import Effect
Effect
.
const fail: <Error>(error: Error) => Effect.Effect<never, Error, never>

Creates an `Effect` that represents a recoverable error. This `Effect` does not succeed but instead fails with the provided error. The failure can be of any type, and will propagate through the effect pipeline unless handled. Use this function when you want to explicitly signal an error in an `Effect` computation. The failed effect can later be handled with functions like {@link catchAll } or {@link catchTag } .

fail
(new
var Error: ErrorConstructor new (message?: string) => Error
Error
("Oh uh!")).
(method) Pipeable.pipe<Effect.Effect<never, Error, never>, Effect.Effect<string, Error, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<never, Error, never>) => Effect.Effect<string, Error, never>): Effect.Effect<...> (+21 overloads)
pipe
(
6
import Effect
Effect
.
const as: <string>(value: string) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<string, E, R> (+1 overload)

This function maps the success value of an `Effect` value to a specified constant value.

as
("primary result")
7
)
8
9
// ┌─── Effect<string, Cause<Error>, never>
10
// ▼
11
const
const sandboxed: Effect.Effect<string, Cause<Error>, never>
sandboxed
=
import Effect
Effect
.
const sandbox: <string, Error, never>(self: Effect.Effect<string, Error, never>) => Effect.Effect<string, Cause<Error>, never>

Exposes the full `Cause` of failure for the specified effect.

sandbox
(
const task: Effect.Effect<string, Error, never>
task
)
12
13
const
const program: Effect.Effect<string, Empty | Sequential<Error> | Parallel<Error>, never>
program
=
import Effect
Effect
.
const catchTags: <never, Cause<Error>, string, { Die: (cause: Die) => Effect.Effect<string, never, never>; Interrupt: (cause: Interrupt) => Effect.Effect<string, never, never>; Fail: (cause: Fail<...>) => Effect.Effect<...>; }>(self: Effect.Effect<...>, cases: { ...; }) => Effect.Effect<...> (+1 overload)

Recovers from the specified tagged errors.

catchTags
(
const sandboxed: Effect.Effect<string, Cause<Error>, never>
sandboxed
, {
14
(property) Die: (cause: Die) => Effect.Effect<string, never, never>
Die
: (
(parameter) cause: Die
cause
) =>
15
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>
log
(`Caught a defect: ${
(parameter) cause: Die
cause
.
(property) Die.defect: unknown
defect
}`).
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<string, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<string, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
16
import Effect
Effect
.
const as: <string>(value: string) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<string, E, R> (+1 overload)

This function maps the success value of an `Effect` value to a specified constant value.

as
("fallback result on defect")
17
),
18
(property) Interrupt: (cause: Interrupt) => Effect.Effect<string, never, never>
Interrupt
: (
(parameter) cause: Interrupt
cause
) =>
19
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>
log
(`Caught a defect: ${
(parameter) cause: Interrupt
cause
.
(property) Interrupt.fiberId: FiberId
fiberId
}`).
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<string, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<string, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
20
import Effect
Effect
.
const as: <string>(value: string) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<string, E, R> (+1 overload)

This function maps the success value of an `Effect` value to a specified constant value.

as
("fallback result on fiber interruption")
21
),
22
(property) Fail: (cause: Fail<Error>) => Effect.Effect<string, never, never>
Fail
: (
(parameter) cause: Fail<Error>
cause
) =>
23
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>
log
(`Caught a defect: ${
(parameter) cause: Fail<Error>
cause
.
(property) Fail<Error>.error: Error
error
}`).
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<string, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<string, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
24
import Effect
Effect
.
const as: <string>(value: string) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<string, E, R> (+1 overload)

This function maps the success value of an `Effect` value to a specified constant value.

as
("fallback result on failure")
25
)
26
})
27
28
// Restore the original error handling with unsandbox
29
const
const main: Effect.Effect<string, Error, never>
main
=
import Effect
Effect
.
const unsandbox: <string, Error, never>(self: Effect.Effect<string, Cause<Error>, never>) => Effect.Effect<string, Error, never>

The inverse operation `sandbox(effect)` Terminates with exceptions on the `Left` side of the `Either` error, if it exists. Otherwise extracts the contained `Effect<A, E, R>`

unsandbox
(
const program: Effect.Effect<string, Empty | Sequential<Error> | Parallel<Error>, never>
program
)
30
31
import Effect
Effect
.
const runPromise: <string, Error>(effect: Effect.Effect<string, Error, never>, options?: { readonly signal?: AbortSignal; } | undefined) => Promise<string>

Executes an effect and returns a `Promise` that resolves with the result. Use `runPromise` when working with asynchronous effects and you need to integrate with code that uses Promises. If the effect fails, the returned Promise will be rejected with the error.

runPromise
(
const main: Effect.Effect<string, Error, never>
main
).
(method) Promise<string>.then<void, never>(onfulfilled?: ((value: string) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<...>

Attaches callbacks for the resolution and/or rejection of the Promise.

then
(
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) globalThis.Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
)
32
/*
33
Output:
34
Caught a defect: Oh uh!
35
fallback result on failure
36
*/