Skip to main content
The Errors module provides a hierarchy of error classes designed for CLI applications, with support for error chaining, structured field errors, and machine-readable error codes.

Classes

BaseError

Base error class with support for short messages, detail extraction from cause chains, and cause traversal.
shortMessage
string
required
The short, human-readable error message (without details)
options
BaseError.Options
Configuration options for the error
name
string
The error name: 'Incur.BaseError'
shortMessage
string
The short, human-readable error message
details
string | undefined
Details extracted from the cause’s message, if any
message
string
The full error message, combining shortMessage and details

Usage

import { BaseError } from 'incur'

const cause = new Error('Connection timed out after 30s')
const error = new BaseError('Failed to connect to database', { cause })

console.log(error.shortMessage)
// 'Failed to connect to database'

console.log(error.details)
// 'Connection timed out after 30s'

console.log(error.message)
// 'Failed to connect to database\n\nDetails: Connection timed out after 30s'

Method: walk

Traverses the cause chain. Without a callback, returns the deepest cause. With a callback, returns the first cause where the callback returns true.
fn
(error: unknown) => boolean
Optional predicate function to find a specific error in the cause chain
return
unknown
The deepest cause (no callback) or the first matching cause (with callback)
import { BaseError } from 'incur'

const rootCause = new Error('ECONNREFUSED')
const networkError = new Error('Network unreachable', { cause: rootCause })
const appError = new BaseError('Failed to fetch data', { cause: networkError })

// Get deepest cause
const deepest = appError.walk()
console.log(deepest) // Error: ECONNREFUSED

// Find specific error
const networkErr = appError.walk((err) => 
  err instanceof Error && err.message.includes('Network')
)
console.log(networkErr) // Error: Network unreachable

IncurError

CLI-specific error with machine-readable error codes, actionable hints, and retry flags.
options
IncurError.Options
required
Configuration options for the error
name
string
The error name: 'Incur.IncurError'
code
string
Machine-readable error code (e.g., 'NOT_AUTHENTICATED', 'RATE_LIMITED')
hint
string | undefined
Actionable hint for the user to resolve the error
retryable
boolean
Whether the operation can be retried. Defaults to false.

Usage

import { IncurError } from 'incur'

throw new IncurError({
  code: 'NOT_AUTHENTICATED',
  message: 'Authentication required to access this resource',
  hint: 'Run `mycli login` to authenticate',
  retryable: false
})

Usage: Retryable Errors

import { IncurError } from 'incur'

function fetchData() {
  throw new IncurError({
    code: 'RATE_LIMITED',
    message: 'API rate limit exceeded',
    hint: 'Wait 60 seconds before retrying',
    retryable: true
  })
}

try {
  fetchData()
} catch (err) {
  if (err instanceof IncurError && err.retryable) {
    console.log('Retrying in 60 seconds...')
    // Implement retry logic
  }
}

Usage: Error Codes

import { IncurError } from 'incur'

enum ErrorCode {
  NOT_FOUND = 'NOT_FOUND',
  PERMISSION_DENIED = 'PERMISSION_DENIED',
  INVALID_INPUT = 'INVALID_INPUT'
}

function handleError(err: IncurError) {
  switch (err.code) {
    case ErrorCode.NOT_FOUND:
      console.error('Resource not found:', err.message)
      break
    case ErrorCode.PERMISSION_DENIED:
      console.error('Access denied:', err.hint)
      break
    case ErrorCode.INVALID_INPUT:
      console.error('Invalid input:', err.message)
      break
  }
}

ValidationError

Validation error with per-field error details, typically thrown by the parser when Zod validation fails.
options
ValidationError.Options
required
Configuration options for the error
name
string
The error name: 'Incur.ValidationError'
fieldErrors
FieldError[]
Array of per-field validation errors

Usage

import { ValidationError } from 'incur'

throw new ValidationError({
  message: 'Validation failed',
  fieldErrors: [
    {
      path: 'email',
      expected: 'string (email format)',
      received: 'invalid-email',
      message: 'Invalid email address'
    },
    {
      path: 'age',
      expected: 'number',
      received: 'string',
      message: 'Expected number, received string'
    }
  ]
})

Usage: Display Field Errors

import { ValidationError } from 'incur'

try {
  // Some validation that throws ValidationError
} catch (err) {
  if (err instanceof ValidationError) {
    console.error('Validation failed:')
    for (const fieldError of err.fieldErrors) {
      console.error(`  ${fieldError.path}: ${fieldError.message}`)
      console.error(`    Expected: ${fieldError.expected}`)
      console.error(`    Received: ${fieldError.received}`)
    }
  }
}

ParseError

Error thrown when argument parsing fails (unknown flags, missing values, invalid syntax).
options
ParseError.Options
required
Configuration options for the error
name
string
The error name: 'Incur.ParseError'

Usage

import { ParseError } from 'incur'

throw new ParseError({
  message: 'Unknown flag: --invalid-flag'
})

Usage: Parse Error Handling

import { parse, ParseError } from 'incur'

try {
  const { args, options } = parse(process.argv.slice(2), {
    options: z.object({ verbose: z.boolean() })
  })
} catch (err) {
  if (err instanceof ParseError) {
    console.error('Error:', err.message)
    console.error('Run with --help for usage information')
    process.exit(1)
  }
  throw err
}

Types

FieldError

A field-level validation error detail.
path
string
The field path that failed validation (e.g., 'email', 'user.address.zip')
expected
string
The expected value or type (e.g., 'string', 'number', 'email format')
received
string
The value that was received
message
string
Human-readable validation message
type FieldError = {
  path: string
  expected: string
  received: string
  message: string
}

BaseError.Options

Options for constructing a BaseError.
cause
Error | undefined
The underlying cause of this error

IncurError.Options

Options for constructing an IncurError.
code
string
required
Machine-readable error code
message
string
required
Human-readable error message
hint
string | undefined
Actionable hint for the user
retryable
boolean | undefined
Whether the operation can be retried. Defaults to false.
cause
Error | undefined
The underlying cause

ValidationError.Options

Options for constructing a ValidationError.
message
string
required
Human-readable error message
fieldErrors
FieldError[] | undefined
Per-field validation errors
cause
Error | undefined
The underlying cause

ParseError.Options

Options for constructing a ParseError.
message
string
required
Human-readable error message
cause
Error | undefined
The underlying cause

Error Hierarchy

All error classes extend BaseError, which extends the native Error class:
Error (native)
  └─ BaseError
      ├─ IncurError
      ├─ ValidationError
      └─ ParseError
This allows you to catch errors at different levels of specificity:
import { BaseError, IncurError, ValidationError, ParseError } from 'incur'

try {
  // CLI operation
} catch (err) {
  if (err instanceof ValidationError) {
    // Handle validation errors specifically
  } else if (err instanceof ParseError) {
    // Handle parse errors
  } else if (err instanceof IncurError) {
    // Handle other CLI errors
  } else if (err instanceof BaseError) {
    // Handle any BaseError
  } else {
    // Handle unknown errors
  }
}

Build docs developers (and LLMs) love