Error Handling
Padrone provides a structured error hierarchy so your CLI can distinguish user errors from bugs, show actionable suggestions, and set appropriate exit codes.
Error Hierarchy
Section titled “Error Hierarchy”All Padrone errors extend PadroneError, which carries metadata for user-friendly formatting:
PadroneError (base)├── RoutingError — unknown command, unexpected arguments├── ValidationError — schema validation failures├── ConfigError — config file loading/validation failures└── ActionError — errors thrown from action handlersThrowing Errors in Actions
Section titled “Throwing Errors in Actions”Use ActionError to throw structured errors from your command handlers:
import { createPadrone, ActionError } from 'padrone';import * as z from 'zod/v4';
const program = createPadrone('deploy') .arguments(z.object({ env: z.enum(['staging', 'production']), force: z.boolean().optional(), })) .action(async (args) => { if (args.env === 'production' && !args.force) { throw new ActionError('Production deploys require --force', { exitCode: 1, suggestions: ['Use --force to deploy to production'], }); }
await deploy(args.env); });Error Properties
Section titled “Error Properties”Every PadroneError carries:
| Property | Type | Description |
|---|---|---|
message | string | Human-readable error message |
exitCode | number | Process exit code (default: 1) |
suggestions | string[] | Actionable hints shown to the user |
command | string | undefined | The command path that produced the error |
phase | string | undefined | Which phase failed: 'parse', 'validate', 'execute', or 'config' |
cause | unknown | Original error for chaining |
Catching Errors
Section titled “Catching Errors”With cli()
Section titled “With cli()”cli() throws errors. Catch them to customize the exit behavior:
try { await program.cli();} catch (error) { if (error instanceof PadroneError) { console.error(error.message); if (error.suggestions.length > 0) { console.error('\nSuggestions:'); for (const s of error.suggestions) { console.error(` - ${s}`); } } process.exit(error.exitCode); } throw error; // Re-throw unexpected errors}With eval()
Section titled “With eval()”eval() uses soft error handling — validation failures are returned as argsResult.issues rather than thrown:
const result = await program.eval('deploy --env invalid');
if (result.argsResult?.issues) { for (const issue of result.argsResult.issues) { console.error(`${issue.path?.join('.')}: ${issue.message}`); }}
if (result.error) { // Action threw an error console.error(result.error);}Validation Errors
Section titled “Validation Errors”ValidationError carries the structured issues from schema validation:
import { ValidationError } from 'padrone';
try { await program.cli();} catch (error) { if (error instanceof ValidationError) { for (const issue of error.issues) { console.error(` ${issue.path?.join('.') ?? ''}: ${issue.message}`); } }}Error Handling with Interceptors
Section titled “Error Handling with Interceptors”Interceptors can intercept errors in the error phase to log, transform, or suppress them. The built-in help extension uses this same mechanism to display help text alongside routing/validation errors in CLI mode.
import { defineInterceptor } from 'padrone';
const errorReporter = defineInterceptor({ name: 'error-reporter' }, () => ({ error: (ctx, next) => { reportToSentry(ctx.error); return next(); // Pass through },}));
const errorRecovery = defineInterceptor({ name: 'error-recovery' }, () => ({ error: (ctx, next) => { if (ctx.error instanceof NetworkError) { // Suppress error and return fallback result return { error: undefined, result: cachedValue }; } // Transform the error return { error: new ActionError('Something went wrong', { cause: ctx.error }) }; },}));The error phase only runs during eval() and cli(). See the Interceptors & Extensions guide for full details.
Serialization
Section titled “Serialization”All Padrone errors have a toJSON() method for non-terminal contexts (APIs, web UIs):
try { await program.cli();} catch (error) { if (error instanceof PadroneError) { // { name, message, exitCode, suggestions, command, phase } res.status(500).json(error.toJSON()); }}ValidationError.toJSON() also includes the issues array.
Error Classes Reference
Section titled “Error Classes Reference”| Class | Phase | When |
|---|---|---|
RoutingError | parse | Unknown command, unexpected arguments |
ValidationError | validate | Schema validation failures |
ConfigError | config | Config file not found, invalid format |
ActionError | execute | Thrown from user action handlers |
PadroneError | any | Base class for custom errors |