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.
The short, human-readable error message (without details)
Configuration options for the error
The error name: 'Incur.BaseError'
The short, human-readable error message
Details extracted from the cause’s message, if any
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
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
The error name: 'Incur.IncurError'
Machine-readable error code (e.g., 'NOT_AUTHENTICATED', 'RATE_LIMITED')
Actionable hint for the user to resolve the error
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
The error name: 'Incur.ValidationError'
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
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.
The field path that failed validation (e.g., 'email', 'user.address.zip')
The expected value or type (e.g., 'string', 'number', 'email format')
The value that was received
Human-readable validation message
type FieldError = {
path: string
expected: string
received: string
message: string
}
BaseError.Options
Options for constructing a BaseError.
The underlying cause of this error
IncurError.Options
Options for constructing an IncurError.
Machine-readable error code
Human-readable error message
Actionable hint for the user
Whether the operation can be retried. Defaults to false.
ValidationError.Options
Options for constructing a ValidationError.
Human-readable error message
Per-field validation errors
ParseError.Options
Options for constructing a ParseError.
Human-readable error message
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
}
}