Errors are data. Define them like it.
A typed error registry for TypeScript. Works anywhere—servers, CLIs, libraries, full-stack apps.
We spend time defining database schemas and validating inputs. But errors? We usually just wing it.
throw new Error('User not found') // ← What is this? Who handles it? Who knows.- Central codes registry with typed
props - Fully typed helpers with autocomplete:
errors.create(),errors.is(),errors.match(),errors.hasTag() - Built-in serialize/deserialize across boundaries
- Optional scoped zones for complex services
- Plugins — extend with pre-defined error sets from shared packages
- Zero runtime dependencies
npm install errataimport { code, errata, props } from 'errata'
const errors = errata({
codes: {
'app.internal_error': {
status: 500,
message: 'Internal error',
},
'user.not_found': code({
status: 404,
message: ({ details }) => `User ${details.userId} not found`,
details: props<{ userId: string }>(),
tags: ['auth', 'user'] as const,
}),
'auth.unauthorized': code({
status: 401,
message: 'Not authenticated',
expose: true,
tags: ['auth', 'security'] as const,
}),
}
})
// Create and throw
throw errors.create('user.not_found', { userId: '123' })
// Check
if (errors.is(e, 'auth.unauthorized')) { ... }
// Match
errors.match(e, {
'user.not_found': () => show404(),
'auth.unauthorized': () => redirect('/login'),
})
// Check tags
if (errors.hasTag(e, 'security')) { ... }
// Other helpers
errors.ensure(e, 'user.not_found') // throws if not this error
const [data, err] = await errors.safe(() => fetchUser(id)) // typed [result, error] tuple
const json = errors.serialize(e) // for sending across boundaries
const err = errors.deserialize(json) // restore on other sideExtend your registry with pre-defined error sets from shared packages:
import { myBackendErrors } from '@my-org/api-errors'
import { errata } from 'errata'
const errors = errata({
codes: {
'app.unknown': { status: 500, message: 'Something went wrong' }
},
plugins: [myBackendErrors()]
})
// Now you can handle backend errors with full type safety
errors.match(e, {
'payment.declined': () => showCardError(),
'rate_limit': () => retry(),
})MIT License © Franco P. Romano L.