Skip to content

Err

Error handling utilities for robust error management.

Provides utilities for error inspection, stack trace manipulation, try-catch wrappers, type guards, and null safety. Features formatted error logging and error wrapping utilities.

Import

typescript
import { Err } from '@wollybeard/kit'
typescript
import * as Err from '@wollybeard/kit/err'

Conversion

[F] ensure

typescript
(value: unknown): Error

Ensure that the given value is an error and return it. If it is not an error than wrap it in one, passing the given value as the error message.

Inspection

[F] log

typescript
(error: Error, options?: { color?: boolean; stackTraceColumns?: number; identColumns?: number; maxFrames?: number; showHelp?: boolean; } | undefined): void

Log an error to console with nice formatting.

[T] InspectOptions

typescript
type InspectOptions = InferOptions<typeof optionSpecs>

Options for configuring error inspection output. All options can be overridden via environment variables.

color

  • Whether to use ANSI color codes for better readability (default: true, env: ERROR_DISPLAY_COLOR)

stackTraceColumns

  • Maximum column width before truncating stack trace lines (default: 120, env: ERROR_DISPLAY_STACK_TRACE_COLUMNS)

identColumns

  • Number of spaces to use for indentation (default: 4, env: ERROR_DISPLAY_IDENT_COLUMNS)

maxFrames

  • Maximum number of stack frames to show; 0 to hide stack traces entirely (default: 10, env: ERROR_DISPLAY_MAX_FRAMES)

showHelp

  • Whether to display the environment variable help section (default: true, env: ERROR_DISPLAY_SHOW_HELP)

Examples:

typescript
// Use default options
Err
.inspect(error)
// Customize options
Err
.inspect(error, {
color
: false,
stackTraceColumns
: 200,
showHelp
: false,
}) // Hide stack traces (useful for test snapshots)
Err
.inspect(error, {
maxFrames
: 0,
showHelp
: false,
color
: false })
// Set via environment variables
process
.
env
.
ERROR_DISPLAY_COLOR
= 'false'
process
.
env
.
ERROR_DISPLAY_SHOW_HELP
= 'false'

[F] inspect

typescript
(error: Error, options?: { color?: boolean; stackTraceColumns?: number; identColumns?: number; maxFrames?: number; showHelp?: boolean; } | undefined): string

Parameters:

  • error - The error to inspect
  • options - Optional configuration for formatting

Returns: A formatted string representation of the error

Render an error to a string with detailed formatting.

Features:

  • Nested error support (causes and aggregate errors)
  • Context object formatting
  • Stack trace cleaning with filtering indicators
  • Tree-like visual guides for nested structures
  • Configurable via options or environment variables

Examples:

typescript
// Simple error
const 
error
= new
Error
('Something went wrong')
console
.
log
(
Err
.inspect(
error
))
// Error with context const
contextError
= new
Error
('API failed')
context
Error
.context = {
userId
: 123,
endpoint
: '/api/users' }
console
.
log
(
Err
.inspect(
contextError
))
// Aggregate error with multiple failures const
errors
= [
new
Error
('Database connection failed'),
new
Error
('Redis timeout'),
] const
aggregate
= new
AggregateError
(
errors
, 'Multiple services failed')
console
.
log
(
Err
.inspect(
aggregate
))
// Disable help section
console
.
log
(
Err
.inspect(
error
, {
showHelp
: false }))

Stack Traces

[I] StackOptions

typescript
interface StackOptions {
  /**
   * Remove internal library frames from the stack trace.
   * @default true
   */
  removeInternal?: boolean

  /**
   * Patterns to filter out from stack traces.
   * @default ['node_modules', 'node:internal']
   */
  filterPatterns?: string[]

  /**
   * Maximum number of frames to show.
   * @default 10
   */
  maxFrames?: number

  /**
   * Include source code context around error location.
   * @default false
   */
  includeSource?: boolean

  /**
   * Number of source lines to show before and after error.
   * @default 2
   */
  sourceContext?: number
}

Options for cleaning and formatting stack traces.

[I] StackFrame

typescript
interface StackFrame {
  /**
   * Function name or <anonymous>
   */
  function: string

  /**
   * File path
   */
  file: string

  /**
   * Line number
   */
  line: number

  /**
   * Column number
   */
  column: number

  /**
   * Whether this is internal to the library
   */
  isInternal: boolean

  /**
   * Whether this is a native V8 frame
   */
  isNative: boolean

  /**
   * Raw frame string
   */
  raw: string
}

Parsed stack frame information.

[F] parseStack

typescript
(stack: string): StackFrame[]

Parse a stack trace string into structured frames.

[I] StackCleanStats

typescript
interface StackCleanStats {
  /**
   * Total number of frames before filtering.
   */
  totalFrames: number

  /**
   * Number of frames filtered out.
   */
  filteredFrames: number

  /**
   * Number of node_modules frames filtered.
   */
  nodeModulesFrames: number

  /**
   * Number of internal frames filtered.
   */
  internalFrames: number

  /**
   * Number of frames shown.
   */
  shownFrames: number

  /**
   * Whether the output was truncated due to maxFrames.
   */
  wasTruncated: boolean
}

Statistics about stack trace filtering. Provides detailed information about what was filtered during stack cleaning.

Examples:

typescript
const 
result
= cleanStackWithStats(error.stack)
console
.
log
(`Filtered ${
result
.stats.filteredFrames} frames`)
console
.
log
(
`Showing ${
result
.stats.shownFrames} of ${
result
.stats.totalFrames} total`,
)

[I] CleanStackResult

typescript
interface CleanStackResult {
  /**
   * The cleaned stack trace string.
   */
  stack: string

  /**
   * Statistics about what was filtered.
   */
  stats: StackCleanStats
}

Result of cleaning a stack trace. Contains both the cleaned stack string and statistics about what was filtered.

[F] cleanStackWithStats

typescript
(stack: string, options?: StackOptions | undefined): CleanStackResult

Parameters:

  • stack - The raw stack trace string to clean
  • options - Optional configuration for filtering and formatting

Returns: Object containing cleaned stack and filtering statistics

Clean a stack trace by removing internal frames and applying filters. Returns both the cleaned stack and detailed statistics about filtering.

Examples:

typescript
const 
error
= new
Error
('Something failed')
const
result
=
Err
.cleanStackWithStats(
error
.
stack
, {
removeInternal
: true,
filterPatterns
: ['node_modules'],
maxFrames
: 10,
})
console
.
log
(
result
.stack) // Cleaned stack trace
console
.
log
(`Filtered ${
result
.stats.nodeModulesFrames} node_modules frames`)

[F] cleanStack

typescript
(stack: string, options?: StackOptions | undefined): string

Parameters:

  • stack - The raw stack trace string to clean
  • options - Optional configuration for filtering

Returns: The cleaned stack trace string

DEPRECATED

Use cleanStackWithStats for detailed filtering information

Clean a stack trace by removing internal frames and applying filters.

[F] formatFrame

typescript
(frame: StackFrame): string

Format a stack frame for better readability.

[Class] CleanError

typescript
class {
  constructor(message: string, options?: (ErrorOptions & { context?: object; stackOptions?: StackOptions; }) | undefined)

  // Properties
  originalStack?: string | undefined
  context?: object | undefined
}

Properties:

  • originalStack - Original uncleaned stack trace.
  • context - Additional context for the error.

Enhanced Error class that automatically cleans stack traces.

[F] mergeStacks

typescript
(wrapper: Error, cause: Error): string

Merge stack traces from multiple errors (useful for wrapped errors). This preserves the full error chain while removing duplicates.

Try-Catch

[F] tryCatch

typescript
<returned, thrown > (promise: Promise<returned>, predicates ?: readonly[TypePredicate<thrown>, ...TypePredicate < thrown > []] | undefined): Promise < returned | (IsUnknown<thrown> extends true ? Error : thrown)>
  <returned, thrown > (fn: () => returned, predicates ?: readonly[TypePredicate<thrown>, ...TypePredicate < thrown > []] | undefined): AwaitedUnion < returned, IsUnknown<thrown> extends true ? Error : thrown >
    <returned, thrown > (fnOrPromise: Promise<any> | (() => returned), predicates ?: readonly[TypePredicate<thrown>, ...TypePredicate < thrown > []] =[
      is as Bool.TypePredicate<thrown>,
    ]): any

Parameters:

  • predicates - Type predicates to filter which errors to catch (defaults to all Error instances)

Returns: The result if successful, or the caught error

Try to execute a function or resolve a promise, catching errors instead of throwing. Returns either the successful result or the caught error.

Examples:

typescript
// With function
const 
result
=
Err
.tryCatch(() =>
JSON
.
parse
(input)) // parsed value | Error
// With promise const
data
= await
Err
.tryCatch(
fetch
(url)) // Response | Error
// With custom predicates const
isNetworkError
= (
e
: unknown):
e
is
NetworkError
=>
e
instanceof
Error
&&
e
.
name
=== 'NetworkError'
const
response
=
Err
.tryCatch(
() =>
fetch
(url),
[
isNetworkError
],
) // Response | NetworkError

[T] TryCatchDefaultPredicateTypes

typescript
type TryCatchDefaultPredicateTypes = Error

Default error types caught by try/catch functions when no predicates are specified.

[F] tryCatchify

typescript
<fn extends Fn.AnyAny, thrown > (fn: fn, predicates ?: readonly[TypePredicate<thrown>, ...TypePredicate < thrown > []] =[is as Bool.TypePredicate<thrown>]): (...args: Parameters<fn>) => AwaitedUnion<ReturnType<fn>, IsUnknown<thrown> extends true ? Error : thrown>

Parameters:

  • fn - The function to transform
  • predicates - Type predicates to filter which errors to catch (defaults to all Error instances)

Returns: A new function that returns results or errors instead of throwing

Transform a function to return caught errors instead of throwing them. The transformed function will return either the result or the caught error.

Examples:

typescript
// Transform a throwing function
const 
parse
JsonSafe
=
Err
.tryCatchify(
JSON
.
parse
)
const
result
=
parseJsonSafe
('{"valid": true}') // { valid: true }
const
error
=
parseJsonSafe
('invalid') // SyntaxError
// With custom error predicates const
isNetworkError
= (
e
: unknown):
e
is
NetworkError
=>
e
instanceof
Error
&&
e
.
name
=== 'NetworkError'
const
fetchSafe
=
Err
.tryCatchify(
fetch
, [
isNetworkError
])
const
response
= await
fetchSafe
(url) // Response | NetworkError

[F] tryCatchIgnore

typescript
<$Return>(fn: () => $Return): $Return

Parameters:

  • fn - The function to execute

Returns: The result of the function if successful, undefined otherwise

Try to execute a function and silently ignore any errors. Returns the result if successful, or undefined if it throws. For async functions, errors are silently caught without rejection.

Examples:

typescript
// Sync function
Err
.tryCatchIgnore(() =>
JSON
.
parse
(invalidJson)) // returns undefined
// Async function await
Err
.tryCatchIgnore(async () => {
throw new
Error
('Network error')
}) // returns undefined, no rejection

Try-Or

[F] tryOrRethrow

typescript
<$Return>(fn: () => $Return, wrapper: string | WrapOptions | ((cause: Error) => Error)): $Return extends Promise<any> ? $Return : $Return

Parameters:

  • fn - The function to execute
  • wrapper - Either a string message, options object, or a function that wraps the error

Returns: The result of the function if successful

Throws:

  • The wrapped error if the function throws

Try to execute a function and wrap any thrown errors with a higher-level message. Handles both synchronous and asynchronous functions automatically.

Examples:

typescript
// Simple string message
const 
data
= await
Err
.tryOrRethrow(
fetchData, 'Failed to fetch data', ) // With options const
user
= await
Err
.tryOrRethrow(
() => fetchUser(userId), {
message
: 'Failed to fetch user',
context
: {
userId
} },
) // With wrapper function const
result
= await
Err
.tryOrRethrow(
riskyOperation, wrapWith('Operation failed'), ) // Custom error wrapper const
config
= await
Err
.tryOrRethrow(
loadConfig, (
cause
) => new ConfigError('Failed to load config', {
cause
}),
)

[F] tryAllOrRethrow

typescript
<$Fns extends readonly [() => any, ...Array<() => any>]>(fns: $Fns, wrapper: string | WrapOptions | ((cause: Error) => Error)): Promise<{ [K in keyof $Fns]: Awaited<ReturnType<$Fns[K]>>; }>

Parameters:

  • fns - Array of functions to execute
  • wrapper - Either a string message, options object, or a function that wraps the error

Returns: Array of results if all succeed

Throws:

  • AggregateError with wrapped individual errors if any fail

Try multiple functions and wrap any errors with a higher-level message. If any function throws, all errors are collected into an AggregateError.

Examples:

typescript
const [
users
,
posts
] = await
Err
.tryAllOrRethrow(
[fetchUsers, fetchPosts], 'Failed to load data', ) // With context const [
config
,
schema
,
data
] = await
Err
.tryAllOrRethrow(
[loadConfig, loadSchema, loadData], {
message
: 'Failed to initialize',
context
: {
env
: 'production' } },
)

[F] tryOr

typescript
<success, fallback > (fn: () => success, fallback: LazyMaybe<fallback>): TryOrReturn<success, fallback>

Parameters:

  • fn - The function to execute
  • fallback - The fallback value or function (must be sync if fn is sync)

Returns: The result of the function if successful, or the fallback value if it throws

Try to execute a function and return a fallback value if it throws.

Type constraints:

  • If fn is synchronous, fallback must also be synchronous
  • If fn is asynchronous, fallback can be either sync or async
  • For sync functions with async fallbacks, use tryOrAsync instead

Examples:

typescript
// Sync function with sync fallback
const 
data
=
Err
.tryOr(
() =>
JSON
.
parse
(input),
{
error
: 'Invalid JSON' },
) // Async function with sync fallback const
config
= await
Err
.tryOr(
async () => loadConfig(), () => getDefaultConfig(), ) // Async function with async fallback const
data
= await
Err
.tryOr(
async () => fetchFromPrimary(), async () => fetchFromSecondary(), ) // This would be a TYPE ERROR: // const bad = Err.tryOr( // () => 42, // sync // async () => 'fallback' // async - not allowed! // )

[F] tryOrAsync

typescript
<success, fallback > (fn: () => success, fallback: LazyMaybe<fallback>): Promise<Awaited<success> | Awaited<fallback>>

Parameters:

  • fn - The function to execute (sync or async)
  • fallback - The fallback value or function (sync or async)

Returns: Always returns a Promise of the result or fallback

Try to execute a function and return a fallback value if it throws. Always returns a Promise, allowing async fallbacks for sync functions.

Use this when:

  • You have a sync function with an async fallback
  • You want consistent async behavior regardless of input types

Examples:

typescript
// Sync function with async fallback
const 
data
= await
Err
.tryOrAsync(
() => readFileSync('config.json'), async () => fetchDefaultConfig(), ) // Ensures consistent Promise return const
result
= await
Err
.tryOrAsync(
() => 42, () => 'fallback', ) // Always Promise<number | string>

[F] tryOrAsyncOn

typescript
<success>(fn: () => success): <fallback>(fallback: LazyMaybe<fallback>) => Promise<Awaited<success> | Awaited<fallback>>

Curried version of tryOrAsync that takes the function first. Useful for creating reusable async error handlers.

Examples:

typescript
const 
parse
JsonOrFetch
=
Err
.tryOrAsyncOn(() =>
JSON
.
parse
(input))
const
data
= await
parseJsonOrFetch
(async () => fetchDefault())

[F] tryOrAsyncWith

typescript
<fallback>(fallback: LazyMaybe<fallback>): <success>(fn: () => success) => Promise<Awaited<success> | Awaited<fallback>>

Curried version of tryOrAsync that takes the fallback first. Always returns a Promise regardless of input types.

Examples:

typescript
const 
orFetchDefault
=
Err
.tryOrAsyncWith(async () => fetchDefault())
const
data1
= await
orFetchDefault
(() => localData())
const
data2
= await
orFetchDefault
(() => cachedData())

[F] tryOrOn

typescript
<success>(fn: () => success): <fallback>(fallback: LazyMaybe<fallback>) => TryOrReturn<success, fallback>

Curried version of tryOr that takes the function first. Useful for creating reusable error handlers.

Note: Same type constraints as tryOr apply

  • sync functions require sync fallbacks.

Examples:

typescript
const 
parse
JsonOr
=
Err
.tryOrOn(() =>
JSON
.
parse
(input))
const
data
=
parseJsonOr
({
error
: 'Invalid JSON' })

[F] tryOrWith

typescript
<fallback>(fallback: LazyMaybe<fallback>): <success>(fn: () => success) => TryOrReturn<success, fallback>

Curried version of tryOr that takes the fallback first. Useful for creating reusable fallback patterns.

Note: Same type constraints as tryOr apply

  • sync functions require sync fallbacks.

Examples:

typescript
const 
orDefault
=
Err
.tryOrWith({
status
: 'unknown',
data
: null })
const
result1
=
orDefault
(() => fetchStatus())
const
result2
=
orDefault
(() => getLatestData())

[C] tryOrUndefined

typescript
;(<success>(fn: () => success) => TryOrReturn<success, undefined>)

Try to execute a function and return undefined if it throws. Shorthand for tryOrWith(undefined).

Examples:

typescript
const 
data
=
Err
.tryOrUndefined(() =>
localStorage
.
getItem
('key'))
// data is string | undefined

[C] tryOrNull

typescript
;(<success>(fn: () => success) => TryOrReturn<success, null>)

Try to execute a function and return null if it throws. Shorthand for tryOrWith(null).

Examples:

typescript
const 
user
= await
Err
.tryOrNull(async () => fetchUser(id))
// user is User | null

Type Guards

[F] is

typescript
(value: unknown): boolean

Parameters:

  • value - The value to check

Returns: True if the value is an Error instance

Type predicate to check if a value is an Error instance.

Examples:

typescript
Err
.is(new
Error
('test')) // true
Err
.is('not an error') // false
Err
.is(null) // false

[F] isAggregateError

typescript
(value: unknown): boolean

Check if a value is an AggregateError instance.

[F] isAbortError

typescript
(error: any): boolean

Parameters:

  • error - The error to check

Returns: True if the error is an AbortError

Check if an error is an AbortError (from AbortController/AbortSignal).

Examples:

typescript
const 
controller
= new
AbortController
()
controller
.
abort
()
try { await
fetch
(url, {
signal
:
controller
.
signal
})
} catch (
error
) {
if (
Err
.isAbortError(
error
)) {
console
.
log
('Request was aborted')
} }

Types

[∩] ContextualError

typescript
type ContextualError<
  $Context extends Record<string, unknown> = Record<string, unknown>,
> = Error & {
  context: $Context
}

An error with additional contextual data.

[T] Context

typescript
type Context = object

Context information that can be attached to errors. Must be an object to ensure it can be properly serialized and inspected.

[I] ErrorWithContext

typescript
interface ErrorWithContext extends Error {
  /**
   * Additional context information about the error.
   */
  context?: Context
}

DEPRECATED

Use ContextualError instead for better type safety.

An error that includes additional context information.

Utilities

[F] throwNull

typescript
<V>(value: V, message ?: string | undefined): Exclude<V, null>

Parameters:

  • value - The value to check
  • message - Optional custom error message

Returns: The value if not null

Throws:

  • Error if the value is null

Throw an error if the value is null, otherwise return the non-null value.

Examples:

typescript
const 
result
=
Err
.throwNull(maybeNull) // throws if null
const
safe
=
Err
.throwNull(maybeNull, 'Custom error message')

[C] defaultThrowNullMessage

typescript
'Unexpected null value.'

Default error message used by throwNull when no custom message is provided.

[F] guardNull

typescript
<fn extends Fn.AnyAny>(fn: fn, message ?: string | undefined): ReturnExclude<null, fn>

Parameters:

  • fn - The function to wrap
  • message - Optional custom error message when null is returned

Returns: A wrapped function that throws on null return values

Wrap a function to throw an error if it returns null.

Examples:

typescript
const 
find
= (
id
: string) => items.find(
item
=>
item
.id ===
id
) ?? null
const
findOrThrow
=
Err
.guardNull(
find
, 'Item not found')
const
item
=
findOrThrow
('123') // throws if not found

[F] createContextualError

typescript
<$Context extends Record<string, unknown>>(message: string, context: $Context): ContextualError<$Context>

Parameters:

  • message - The error message
  • context - Contextual data to attach to the error

Returns: An Error instance with the context attached

Create an error with contextual data about it.

The context object is attached to the error instance and the message property is made enumerable for better debugging experience.

Examples:

typescript
const 
error
=
Err
.createContextualError('Failed to fetch user', {
userId
: '123',
endpoint
: '/api/users',
statusCode
: 404,
})
console
.
log
(
error
.context.userId) // '123'

Wrapping

[I] WrapOptions

typescript
interface WrapOptions {
  /**
   * The error message for the wrapper error.
   */
  message: string
  /**
   * Additional context to attach to the error.
   */
  context?: Context
}

Options for wrapping errors with additional context.

[F] wrap

typescript
(cause: unknown, messageOrOptions: string | WrapOptions): Error

Parameters:

  • cause - The error to wrap (will be set as the cause)
  • messageOrOptions - Either a string message or options with message and context

Returns: A new Error with the given message and the original error as cause

Wrap an error with a higher-level error message. If the input is not an Error, it will be converted to one using ensure.

Examples:

typescript
try {
  await fetchData()
} catch (
error
) {
throw
Err
.wrap(
error
, 'Failed to fetch data')
} // With context try { await fetchUser(userId) } catch (
error
) {
throw
Err
.wrap(
error
, {
message
: 'Failed to fetch user',
context
: {
userId
},
}) }

[C] wrapOn

typescript
;((cause: unknown) => (messageOrOptions: string | WrapOptions) => Error)

Curried version of wrap that takes the error first. Useful for error handling pipelines.

Examples:

typescript
const 
wrapFetchError
=
Err
.wrapOn(networkError)
throw
wrapFetchError
('Failed to fetch data')

[C] wrapWith

typescript
;((messageOrOptions: string | WrapOptions) => (cause: unknown) => Error)

Curried version of wrap that takes the message/options first. Useful for creating reusable error wrappers.

Examples:

typescript
const 
wrapAsFetchError
=
Err
.wrapWith('Failed to fetch data')
try { await fetchData() } catch (
error
) {
throw
wrapAsFetchError
(
error
)
} // With context const
wrapAsUserError
=
Err
.wrapWith({
message
: 'Failed to process user',
context
: {
operation
: 'update' },
})

Other

[T] _InferOptions

typescript
type _InferOptions<
  $EnvironmentConfigurableOptions extends EnvironmentConfigurableOptionSpec[],
> = {
  [i in keyof $EnvironmentConfigurableOptions]: {
    [_ in $EnvironmentConfigurableOptions[i]['name']]?: ReturnType<
      $EnvironmentConfigurableOptions[i]['parse']
    >
  }
}

[F] captureStackTrace

typescript
(message?: string = 'Captured stack'): string

Capture the current stack trace at a specific point. Useful for adding trace information without throwing.

[F] getCaller

typescript
(depth?: number = 1): StackFrame | undefined

Get the caller information from the current stack.

[F] tryCatch

typescript
<returned, thrown > (promise: Promise<returned>, predicates ?: readonly[TypePredicate<thrown>, ...TypePredicate < thrown > []] | undefined): Promise < returned | (IsUnknown<thrown> extends true ? Error : thrown)>
  <returned, thrown > (fn: () => returned, predicates ?: readonly[TypePredicate<thrown>, ...TypePredicate < thrown > []] | undefined): AwaitedUnion < returned, IsUnknown<thrown> extends true ? Error : thrown >
    <returned, thrown > (fnOrPromise: Promise<any> | (() => returned), predicates ?: readonly[TypePredicate<thrown>, ...TypePredicate < thrown > []] =[
      is as Bool.TypePredicate<thrown>,
    ]): any

Parameters:

  • predicates - Type predicates to filter which errors to catch (defaults to all Error instances)

Returns: The result if successful, or the caught error

[F] tryCatch

typescript
<returned, thrown > (promise: Promise<returned>, predicates ?: readonly[TypePredicate<thrown>, ...TypePredicate < thrown > []] | undefined): Promise < returned | (IsUnknown<thrown> extends true ? Error : thrown)>
  <returned, thrown > (fn: () => returned, predicates ?: readonly[TypePredicate<thrown>, ...TypePredicate < thrown > []] | undefined): AwaitedUnion < returned, IsUnknown<thrown> extends true ? Error : thrown >
    <returned, thrown > (fnOrPromise: Promise<any> | (() => returned), predicates ?: readonly[TypePredicate<thrown>, ...TypePredicate < thrown > []] =[
      is as Bool.TypePredicate<thrown>,
    ]): any

Parameters:

  • predicates - Type predicates to filter which errors to catch (defaults to all Error instances)

Returns: The result if successful, or the caught error