(
f: <E, A>(options: {
readonly fiber: Fiber.Fiber<A, E>
readonly teardown: Teardown
}) => void
): {
(options?: {
readonly disableErrorReporting?: boolean | undefined
readonly teardown?: Teardown | undefined
}): <E, A>(effect: Effect.Effect<A, E>) => void
<E, A>(
effect: Effect.Effect<A, E>,
options?: {
readonly disableErrorReporting?: boolean | undefined
readonly teardown?: Teardown | undefined
}
): void
}Creates a platform-specific main program runner that handles Effect execution lifecycle.
When to use
Use when building a runtime adapter for a host platform.
Details
The runner executes Effect programs as main entry points. The provided function receives a forked fiber and a teardown callback so it can install platform-specific signal handling, fiber observers, and final exit behavior.
Most applications should use a platform-provided runner, such as
NodeRuntime.runMain, rather than constructing one directly.
disableErrorReporting disables the automatic log emitted for unreported
non-interruption failures. It does not change exit-code calculation or the
custom teardown callback.
Gotchas
The setup function is responsible for observing the fiber and eventually
invoking teardown. makeRunMain also tries to keep the host process alive
with a long interval while the main fiber is running; if the host blocks
timers, the runner still starts but cannot use that keep-alive fallback.
Example (Creating platform runners)
import { Effect, Fiber, Runtime } from "effect"
// Create a simple runner for a hypothetical platform
const runMain = Runtime.makeRunMain(({ fiber, teardown }) => {
// Set up signal handling
const handleSignal = () => {
Effect.runSync(Fiber.interrupt(fiber))
}
// Add signal listeners (platform-specific)
// process.on('SIGINT', handleSignal)
// process.on('SIGTERM', handleSignal)
// Handle fiber completion
fiber.addObserver((exit) => {
teardown(exit, (code) => {
console.log(`Program finished with exit code: ${code}`)
// process.exit(code)
})
})
})
// Use the runner
const program = Effect.gen(function*() {
yield* Effect.log("Starting program")
yield* Effect.sleep(1000)
yield* Effect.log("Program completed")
return "success"
})
// Run with default options
runMain(program)
// Run with custom teardown
runMain(program, {
teardown: (exit, onExit) => {
console.log("Custom teardown logic")
Runtime.defaultTeardown(exit, onExit)
}
})export const const makeRunMain: (
f: <E, A>(options: {
readonly fiber: Fiber.Fiber<A, E>
readonly teardown: Teardown
}) => void
) => {
(options?: {
readonly disableErrorReporting?:
| boolean
| undefined
readonly teardown?: Teardown | undefined
}): <E, A>(effect: Effect.Effect<A, E>) => void
<E, A>(
effect: Effect.Effect<A, E>,
options?: {
readonly disableErrorReporting?:
| boolean
| undefined
readonly teardown?: Teardown | undefined
}
): void
}
Creates a platform-specific main program runner that handles Effect execution lifecycle.
When to use
Use when building a runtime adapter for a host platform.
Details
The runner executes Effect programs as main entry points. The provided
function receives a forked fiber and a teardown callback so it can install
platform-specific signal handling, fiber observers, and final exit behavior.
Most applications should use a platform-provided runner, such as
NodeRuntime.runMain, rather than constructing one directly.
disableErrorReporting disables the automatic log emitted for unreported
non-interruption failures. It does not change exit-code calculation or the
custom teardown callback.
Gotchas
The setup function is responsible for observing the fiber and eventually
invoking teardown. makeRunMain also tries to keep the host process alive
with a long interval while the main fiber is running; if the host blocks
timers, the runner still starts but cannot use that keep-alive fallback.
Example (Creating platform runners)
import { Effect, Fiber, Runtime } from "effect"
// Create a simple runner for a hypothetical platform
const runMain = Runtime.makeRunMain(({ fiber, teardown }) => {
// Set up signal handling
const handleSignal = () => {
Effect.runSync(Fiber.interrupt(fiber))
}
// Add signal listeners (platform-specific)
// process.on('SIGINT', handleSignal)
// process.on('SIGTERM', handleSignal)
// Handle fiber completion
fiber.addObserver((exit) => {
teardown(exit, (code) => {
console.log(`Program finished with exit code: ${code}`)
// process.exit(code)
})
})
})
// Use the runner
const program = Effect.gen(function*() {
yield* Effect.log("Starting program")
yield* Effect.sleep(1000)
yield* Effect.log("Program completed")
return "success"
})
// Run with default options
runMain(program)
// Run with custom teardown
runMain(program, {
teardown: (exit, onExit) => {
console.log("Custom teardown logic")
Runtime.defaultTeardown(exit, onExit)
}
})
makeRunMain = (
f: <E, A>(options: {
readonly fiber: Fiber.Fiber<A, E>
readonly teardown: Teardown
}) => void
f: <function (type parameter) E in <E, A>(options: {
readonly fiber: Fiber.Fiber<A, E>;
readonly teardown: Teardown;
}): void
E, function (type parameter) A in <E, A>(options: {
readonly fiber: Fiber.Fiber<A, E>;
readonly teardown: Teardown;
}): void
A>(
options: {
readonly fiber: Fiber.Fiber<A, E>
readonly teardown: Teardown
}
options: {
readonly fiber: Fiber.Fiber<A, E>(property) fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
fiber: import FiberFiber.type Fiber.Fiber = /*unresolved*/ anyFiber<function (type parameter) A in <E, A>(options: {
readonly fiber: Fiber.Fiber<A, E>;
readonly teardown: Teardown;
}): void
A, function (type parameter) E in <E, A>(options: {
readonly fiber: Fiber.Fiber<A, E>;
readonly teardown: Teardown;
}): void
E>
readonly teardown: Teardownteardown: Teardown
}
) => void
): {
(
options: {
readonly disableErrorReporting?:
| boolean
| undefined
readonly teardown?: Teardown | undefined
}
options?: {
readonly disableErrorReporting?: boolean | undefineddisableErrorReporting?: boolean | undefined
readonly teardown?: Teardown | undefinedteardown?: Teardown | undefined
}
): <function (type parameter) E in <E, A>(effect: Effect.Effect<A, E>): voidE, function (type parameter) A in <E, A>(effect: Effect.Effect<A, E>): voidA>(effect: Effect.Effect<A, E>(parameter) effect: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
effect: import EffectEffect.type Effect.Effect = /*unresolved*/ anyEffect<function (type parameter) A in <E, A>(effect: Effect.Effect<A, E>): voidA, function (type parameter) E in <E, A>(effect: Effect.Effect<A, E>): voidE>) => void
<function (type parameter) E in <E, A>(effect: Effect.Effect<A, E>, options?: {
readonly disableErrorReporting?: boolean | undefined;
readonly teardown?: Teardown | undefined;
}): void
E, function (type parameter) A in <E, A>(effect: Effect.Effect<A, E>, options?: {
readonly disableErrorReporting?: boolean | undefined;
readonly teardown?: Teardown | undefined;
}): void
A>(
effect: Effect.Effect<A, E>(parameter) effect: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
effect: import EffectEffect.type Effect.Effect = /*unresolved*/ anyEffect<function (type parameter) A in <E, A>(effect: Effect.Effect<A, E>, options?: {
readonly disableErrorReporting?: boolean | undefined;
readonly teardown?: Teardown | undefined;
}): void
A, function (type parameter) E in <E, A>(effect: Effect.Effect<A, E>, options?: {
readonly disableErrorReporting?: boolean | undefined;
readonly teardown?: Teardown | undefined;
}): void
E>,
options: {
readonly disableErrorReporting?:
| boolean
| undefined
readonly teardown?: Teardown | undefined
}
options?: {
readonly disableErrorReporting?: boolean | undefineddisableErrorReporting?: boolean | undefined
readonly teardown?: Teardown | undefinedteardown?: Teardown | undefined
}
): void
} =>
import dualdual((args: anyargs) => import EffectEffect.isEffect(args: anyargs[0]), (effect: Effect.Effect<any, any>(parameter) effect: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
effect: import EffectEffect.type Effect.Effect = /*unresolved*/ anyEffect<any, any>, options: {
readonly disableErrorReporting?:
| boolean
| undefined
readonly teardown?: Teardown | undefined
}
options?: {
readonly disableErrorReporting?: boolean | undefineddisableErrorReporting?: boolean | undefined
readonly teardown?: Teardown | undefinedteardown?: Teardown | undefined
}) => {
const const fiber: Fiber.Fiber<any, any>const fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
fiber = options: {
readonly disableErrorReporting?:
| boolean
| undefined
readonly teardown?: Teardown | undefined
}
options?.disableErrorReporting?: boolean | undefineddisableErrorReporting === true
? import EffectEffect.runFork(effect: Effect.Effect<any, any>(parameter) effect: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
effect)
: import EffectEffect.runFork(
import EffectEffect.tapCause(effect: Effect.Effect<any, any>(parameter) effect: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
effect, (cause: Cause.Cause<any>(parameter) cause: {
reasons: ReadonlyArray<Reason<E>>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
cause) => {
if (import CauseCause.hasInterruptsOnly(cause: Cause.Cause<any>(parameter) cause: {
reasons: ReadonlyArray<Reason<E>>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
cause)) return import EffectEffect.void
const const isReported: booleanisReported = const getErrorReported: (
u: unknown
) => boolean
Reads the runtime error-reporting marker from an unknown error value.
When to use
Use to read whether an unknown error value should be treated as already
reported by the default main runner.
Details
Returns a boolean [Runtime.errorReported] property when it is present on an
object. Otherwise returns true, so failures are logged by default.
Gotchas
Non-object values, missing markers, and non-boolean marker values all return
true.
getErrorReported(import CauseCause.squash(cause: Cause.Cause<any>(parameter) cause: {
reasons: ReadonlyArray<Reason<E>>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
cause))
return const isReported: booleanisReported ? import EffectEffect.logError(cause: Cause.Cause<any>(parameter) cause: {
reasons: ReadonlyArray<Reason<E>>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
cause) : import EffectEffect.void
})
)
try {
const const keepAlive: numberkeepAlive = module globalThisglobalThis.function setInterval(
handler: TimerHandler,
timeout?: number,
...arguments: any[]
): number
setInterval(import constVoidconstVoid, 2_147_483_647)
const fiber: Fiber.Fiber<any, any>const fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
fiber.addObserver(() => {
function clearInterval(
id: number | undefined
): void
clearInterval(const keepAlive: numberkeepAlive)
})
} catch {}
const const teardown: Teardownteardown = options: {
readonly disableErrorReporting?:
| boolean
| undefined
readonly teardown?: Teardown | undefined
}
options?.teardown?: Teardown | undefinedteardown ?? const defaultTeardown: TeardownThe default teardown function that determines exit codes from an Effect exit.
When to use
Use as the standard teardown for main programs with conventional process
exit codes and support for
errorExitCode
.
Details
This teardown follows these exit-code rules:
0 for successful completion.
130 for interruption-only failures.
- The squashed error's
errorExitCode
value for other failures when
present.
1 for other failures.
Gotchas
The 130 code is used only when the Cause contains interruptions and no
other failure reasons. Mixed causes use the squashed error path instead.
Example (Referencing default teardown)
import { Exit, Runtime } from "effect"
const logExitCode = (exit: Exit.Exit<any, any>) => {
Runtime.defaultTeardown(exit, (code) => {
console.log(`Exit code: ${code}`)
})
}
logExitCode(Exit.succeed(42))
// Output: Exit code: 0
logExitCode(Exit.fail("error"))
// Output: Exit code: 1
logExitCode(Exit.interrupt(123))
// Output: Exit code: 130
defaultTeardown
return f: <E, A>(options: {
readonly fiber: Fiber.Fiber<A, E>
readonly teardown: Teardown
}) => void
f({ fiber: Fiber.Fiber<any, any>(property) fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
fiber, teardown: Teardownteardown })
})