Skip to content

Fiber.ts

Operations for handles returned by forking effects. A Fiber<A, E> is a lightweight execution of an Effect that may still be running or may already have completed. This module lets callers await or join fiber results, interrupt one or many fibers, check unknown values, access the current fiber, and attach manually managed fibers to a Scope for cleanup.

Since v2.0.0



Returns the current fiber if called from within a fiber context, otherwise returns undefined.

When to use

Use when you need low-level runtime integrations that need access to the currently executing fiber.

Gotchas

This is a synchronous accessor, not an Effect. It returns undefined outside an active fiber runtime context.

Example (Getting the current fiber)

import { Effect, Fiber } from "effect"
const program = Effect.gen(function* () {
const current = Fiber.getCurrent()
if (current) {
console.log(`Current fiber ID: ${current.id}`)
}
})

Signature

declare const getCurrent: () => Fiber<any, any> | undefined

Source

Since v4.0.0

Waits for a fiber to complete and returns its exit value.

When to use

Use when you need to inspect whether the fiber succeeded, failed, died, or was interrupted without propagating the failure.

Details

The returned Effect always succeeds with an Exit describing the fiber’s outcome.

Gotchas

This does not flatten the fiber result into the current Effect. Use join when you want fiber failures to fail the current Effect.

Example (Awaiting a fiber exit)

import { Effect, Fiber } from "effect"
const program = Effect.gen(function* () {
const fiber = yield* Effect.forkChild(Effect.succeed(42))
const exit = yield* Fiber.await(fiber)
console.log(exit) // Exit.succeed(42)
})

Signature

declare const await: <A, E>(self: Fiber<A, E>) => Effect<Exit<A, E>>

Source

Since v2.0.0

Waits for all fibers in the provided iterable to complete and returns an array of their exit values.

When to use

Use when you need every fiber outcome as data, including failures and interruptions.

Details

The returned array is ordered like the input iterable.

Gotchas

Failures are captured as Exit.Failure values. Use joinAll when you want the first failed fiber to fail the returned Effect.

Example (Awaiting multiple fiber exits)

import { Effect, Fiber } from "effect"
const program = Effect.gen(function* () {
const fiber1 = yield* Effect.forkChild(Effect.succeed(1))
const fiber2 = yield* Effect.forkChild(Effect.succeed(2))
const exits = yield* Fiber.awaitAll([fiber1, fiber2])
console.log(exits) // [Exit.succeed(1), Exit.succeed(2)]
})

Signature

declare const awaitAll: <A extends Fiber<any, any>>(
self: Iterable<A>
) => Effect<
Array<Exit<A extends Fiber<infer _A, infer _E> ? _A : never, A extends Fiber<infer _A, infer _E> ? _E : never>>
>

Source

Since v2.0.0

Joins a fiber, blocking until it completes. If the fiber succeeds, returns its value. If it fails, the error is propagated.

When to use

Use when you need a forked fiber’s failure to fail the current Effect because that fiber is part of the current workflow.

Gotchas

Joining a failed fiber propagates the fiber’s Cause. Use await when you need to inspect the Exit instead of failing.

Example (Joining a fiber)

import { Effect, Fiber } from "effect"
const program = Effect.gen(function* () {
const fiber = yield* Effect.forkChild(Effect.succeed(42))
const result = yield* Fiber.join(fiber)
console.log(result) // 42
})

See

  • await for inspecting the fiber outcome as an Exit

Signature

declare const join: <A, E>(self: Fiber<A, E>) => Effect<A, E>

Source

Since v2.0.0

Waits for all fibers to succeed and returns their values in input order.

When to use

Use when you need every fiber to succeed and want the successful values rather than the Exit values.

Details

If any fiber fails, the returned Effect fails with that fiber’s cause and stops waiting for additional results. This does not interrupt the remaining fibers.

Gotchas

A failure stops waiting, but it does not interrupt any other fibers. Use interruptAll separately when remaining fibers should be stopped.

See

  • awaitAll for collecting every fiber outcome as an Exit

Signature

declare const joinAll: <A extends Iterable<Fiber<any, any>>>(
self: A
) => Effect<
Arr.ReadonlyArray.With<A, A extends Iterable<Fiber<infer _A, infer _E>> ? _A : never>,
A extends Fiber<infer _A, infer _E> ? _E : never
>

Source

Since v2.0.0

Checks whether a value is a Fiber. This is a type guard that can be used to determine if an unknown value is a Fiber instance.

When to use

Use when checking values at boundaries where an unknown value may be a runtime fiber.

Details

The check looks for the internal Fiber type ID marker and does not inspect the fiber’s current state.

Example (Checking for fibers)

import { Effect, Fiber } from "effect"
const program = Effect.gen(function* () {
// Create a fiber
const fiber = yield* Effect.forkChild(Effect.succeed(42))
// Test if values are fibers
console.log(Fiber.isFiber(fiber)) // true
console.log(Fiber.isFiber("hello")) // false
console.log(Fiber.isFiber(42)) // false
console.log(Fiber.isFiber(null)) // false
// Use as a type guard
const maybeValue: unknown = fiber
if (Fiber.isFiber(maybeValue)) {
// TypeScript knows maybeValue is a Fiber here
console.log(`Fiber ID: ${maybeValue.id}`)
}
})

Signature

declare const isFiber: (u: unknown) => u is Fiber<unknown, unknown>

Source

Since v2.0.0

Interrupts a fiber, causing it to stop executing and clean up any acquired resources.

When to use

Use when you need to cancel a forked fiber and wait for its cleanup to complete.

Details

The returned Effect completes only after the interrupted fiber has completed.

Gotchas

Interruption is cooperative. A fiber can continue running while it is inside uninterruptible work or finalizers.

Example (Interrupting a fiber)

import { Effect, Fiber } from "effect"
const program = Effect.gen(function* () {
const fiber = yield* Effect.forkChild(Effect.delay("1 second")(Effect.succeed(42)))
yield* Fiber.interrupt(fiber)
console.log("Fiber interrupted")
})

See

  • interruptAs for specifying the interrupting fiber ID
  • await for observing the interrupted fiber’s Exit

Signature

declare const interrupt: <A, E>(self: Fiber<A, E>) => Effect<void>

Source

Since v2.0.0

Interrupts all fibers in the provided iterable, causing them to stop executing and clean up any acquired resources.

When to use

Use when you need to cancel several forked fibers and wait for their cleanup to complete.

Details

The current fiber is recorded as the interruptor. The returned Effect completes only after all interrupted fibers have completed.

Gotchas

Interruption is cooperative for each fiber. The returned Effect can wait for uninterruptible work and finalizers in any interrupted fiber.

Example (Interrupting multiple fibers)

import { Console, Effect, Fiber } from "effect"
const program = Effect.gen(function* () {
// Create multiple long-running fibers
const fiber1 = yield* Effect.forkChild(
Effect.gen(function* () {
yield* Effect.sleep("5 seconds")
yield* Console.log("Task 1 completed")
return "result1"
})
)
const fiber2 = yield* Effect.forkChild(
Effect.gen(function* () {
yield* Effect.sleep("3 seconds")
yield* Console.log("Task 2 completed")
return "result2"
})
)
const fiber3 = yield* Effect.forkChild(
Effect.gen(function* () {
yield* Effect.sleep("4 seconds")
yield* Console.log("Task 3 completed")
return "result3"
})
)
// Wait a bit, then interrupt all fibers
yield* Effect.sleep("1 second")
yield* Console.log("Interrupting all fibers...")
yield* Fiber.interruptAll([fiber1, fiber2, fiber3])
yield* Console.log("All fibers have been interrupted")
})

See

  • interruptAllAs for specifying the interrupting fiber ID

Signature

declare const interruptAll: <A extends Iterable<Fiber<any, any>>>(fibers: A) => Effect<void>

Source

Since v2.0.0

Interrupts all fibers in the provided iterable using the specified fiber ID as the interrupting fiber. This allows you to control which fiber is considered the source of the interruption, which can be useful for debugging and tracing.

When to use

Use to interrupt several fibers while recording a specific fiber ID as the interruptor.

Details

The returned Effect completes only after all interrupted fibers have completed.

Gotchas

The supplied ID affects the recorded interruptor. It does not make interruption synchronous or force uninterruptible regions to stop early.

Example (Interrupting multiple fibers as another fiber)

import { Console, Effect, Fiber } from "effect"
const program = Effect.gen(function* () {
// Create a controlling fiber
const controllerFiber = yield* Effect.forkChild(Effect.succeed("controller"))
// Create multiple worker fibers
const worker1 = yield* Effect.forkChild(
Effect.gen(function* () {
yield* Effect.sleep("5 seconds")
yield* Console.log("Worker 1 completed")
return "worker1"
})
)
const worker2 = yield* Effect.forkChild(
Effect.gen(function* () {
yield* Effect.sleep("3 seconds")
yield* Console.log("Worker 2 completed")
return "worker2"
})
)
// Interrupt all workers using the controller fiber's ID
yield* Effect.sleep("1 second")
yield* Console.log("Interrupting workers from controller...")
yield* Fiber.interruptAllAs([worker1, worker2], controllerFiber.id)
yield* Console.log("All workers interrupted by controller")
})

See

  • interruptAll for using the current fiber as the interruptor

Signature

declare const interruptAllAs: {
(fiberId: number): <A extends Iterable<Fiber<any, any>>>(fibers: A) => Effect<void>
<A extends Iterable<Fiber<any, any>>>(fibers: A, fiberId: number): Effect<void>
}

Source

Since v2.0.0

Interrupts a fiber with a specific fiber ID as the interruptor. This allows tracking which fiber initiated the interruption.

When to use

Use when runtime diagnostics or tracing should attribute the interruption to a specific fiber ID.

Details

The returned Effect completes only after the interrupted fiber has completed.

Gotchas

The supplied ID affects the recorded interruptor. It does not make interruption synchronous or force uninterruptible regions to stop early.

Example (Interrupting a fiber as another fiber)

import { Effect, Fiber } from "effect"
const program = Effect.gen(function* () {
const targetFiber = yield* Effect.forkChild(Effect.delay("5 seconds")(Effect.succeed("task completed")))
// Interrupt the fiber, specifying fiber ID 123 as the interruptor
yield* Fiber.interruptAs(targetFiber, 123)
console.log("Fiber interrupted by fiber #123")
})

See

  • interrupt for using the current fiber as the interruptor

Signature

declare const interruptAs: {
(
fiberId: number | undefined,
annotations?: Context.Context<never> | undefined
): <A, E>(self: Fiber<A, E>) => Effect<void>
<A, E>(self: Fiber<A, E>, fiberId: number | undefined, annotations?: Context.Context<never> | undefined): Effect<void>
}

Source

Since v2.0.0

A runtime fiber is a lightweight thread that executes Effects. Fibers are the unit of concurrency in Effect. They provide a way to run multiple Effects concurrently while maintaining structured concurrency and cancellation safety.

When to use

Use to observe, join, interrupt, or coordinate work that has already been forked.

Details

A fiber exposes both safe Effect-based operations, such as await, join, and interrupt, and low-level runtime fields used by the scheduler and runtime internals.

Gotchas

Prefer the exported functions in this module over calling interruptUnsafe or pollUnsafe directly. The unsafe methods are immediate runtime hooks and do not provide the same Effect-based sequencing guarantees.

Example (Awaiting a forked fiber)

import { Effect, Fiber } from "effect"
const program = Effect.gen(function* () {
// Fork an effect to run in a new fiber
const fiber = yield* Effect.forkChild(Effect.succeed(42))
// Wait for the fiber to complete and get its result
const result = yield* Fiber.await(fiber)
console.log(result) // Exit.succeed(42)
return result
})

Signature

export interface Fiber<out A, out E = never> extends Pipeable {
readonly [TypeId]: Fiber.Variance<A, E>
readonly id: number
readonly currentOpCount: number
readonly getRef: <A>(ref: Context.Reference<A>) => A
readonly context: Context.Context<never>
setContext(context: Context.Context<never>): void
readonly currentScheduler: Scheduler
readonly currentDispatcher: SchedulerDispatcher
readonly currentSpan?: AnySpan | undefined
readonly currentLogLevel: LogLevel
readonly minimumLogLevel: LogLevel
readonly currentStackFrame?: StackFrame | undefined
readonly maxOpsBeforeYield: number
readonly currentPreventYield: boolean
readonly addObserver: (cb: (exit: Exit<A, E>) => void) => () => void
readonly interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void
readonly pollUnsafe: () => Exit<A, E> | undefined
}

Source

Since v2.0.0

Adds a fiber to a Scope and returns the same fiber.

When to use

Use when a manually managed fiber should be interrupted when a Scope closes.

Details

When the scope is closed, the fiber is interrupted. If the scope is already closed, the fiber is interrupted immediately.

Gotchas

This does not wait for the fiber to complete. It only registers the interruption finalizer and returns the same fiber.

See

  • interrupt for interrupting and waiting for completion

Signature

declare const runIn: {
(scope: Scope): <A, E>(self: Fiber<A, E>) => Fiber<A, E>
<A, E>(self: Fiber<A, E>, scope: Scope): Fiber<A, E>
}

Source

Since v4.0.0

The Fiber namespace contains utility types and functions for working with fibers. It provides type-level utilities for fiber operations and variance encoding.

When to use

Use to reference type-level helpers associated with Fiber.

Details

The namespace currently exposes type-level support used by the Fiber interface. Runtime operations are exported as module-level functions.

Example (Working with fiber types)

import { Effect, Fiber } from "effect"
const program = Effect.gen(function* () {
// Create a fiber
const fiber = yield* Effect.forkChild(Effect.succeed(42))
// Use namespace types for variance
const typedFiber: Fiber.Fiber<number, never> = fiber
// Access fiber properties
console.log(`Fiber ID: ${fiber.id}`)
// Join the fiber
const result = yield* Fiber.join(fiber)
return result // 42
})

Source

Since v2.0.0

Variance encoding for the Fiber type, specifying covariance in both the success type A and the error type E.

When to use

Use to carry the success and error type parameters for Fiber in Effect’s type machinery.

Example (Upcasting fibers safely)

import type { Fiber } from "effect"
// Variance allows safe subtyping
declare const fiber: Fiber.Fiber<number, Error>
const upcast: Fiber.Fiber<unknown, unknown> = fiber

Signature

export interface Variance<out A, out E = never> {
readonly _A: Covariant<A>
readonly _E: Covariant<E>
}

Source

Since v2.0.0