try-error Documentation
Error Types
Understanding TryError structure and creating custom error types
TryError Interface
All errors in try-error implement the TryError interface, providing rich context and debugging information:
interface TryError {
readonly type: 'TryError';
readonly message: string;
readonly stack?: string;
readonly source: string;
readonly timestamp: number;
readonly context?: Record<string, unknown>;
readonly cause?: Error | TryError;
}
Properties
type
Always 'TryError'
- used for type discrimination
message
Human-readable error description
stack
Stack trace (when available) for debugging
source
Indicates where the error originated (e.g., 'trySync', 'tryAsync', 'custom')
timestamp
When the error occurred (milliseconds since epoch)
context
Additional debugging information and metadata
cause
The original error that caused this TryError (for error chaining)
Creating Custom Errors
Use the createTryError
function to create custom errors with additional context:
1import { createTryError } from 'try-error';
2
3// Basic custom error
4const validationError = createTryError(
5 'VALIDATION_ERROR',
6 'Email format is invalid'
7);
8
9// Error with context
10const dbError = createTryError(
11 'DATABASE_ERROR',
12 'Failed to connect to database',
13 {
14 host: 'localhost',
15 port: 5432,
16 database: 'myapp',
17 retryAttempt: 3
18 }
19);
20
21// Error with cause (error chaining)
22const parseError = createTryError(
23 'CONFIG_PARSE_ERROR',
24 'Failed to parse configuration file',
25 { filePath: './config.json' },
26 originalError // The original Error that was caught
27);
createTryError Signature
function createTryError(
source: string,
message: string,
context?: Record<string, unknown>,
cause?: Error | TryError
): TryError
Common Error Categories
Here are some common patterns for categorizing errors:
1// Network errors
2const networkError = createTryError(
3 'NETWORK_ERROR',
4 'Request timeout after 5000ms',
5 { url: '/api/users', timeout: 5000 }
6);
7
8// Validation errors
9const validationError = createTryError(
10 'VALIDATION_ERROR',
11 'Invalid email format',
12 { field: 'email', value: 'invalid-email' }
13);
14
15// Authentication errors
16const authError = createTryError(
17 'AUTH_ERROR',
18 'Invalid credentials',
19 { userId: '123', action: 'login' }
20);
21
22// Business logic errors
23const businessError = createTryError(
24 'BUSINESS_ERROR',
25 'Insufficient funds for transaction',
26 {
27 accountId: 'acc_123',
28 requestedAmount: 1000,
29 availableBalance: 500
30 }
31);
32
33// System errors
34const systemError = createTryError(
35 'SYSTEM_ERROR',
36 'Database connection failed',
37 {
38 service: 'postgresql',
39 host: 'db.example.com',
40 port: 5432
41 }
42);
Error Factories
Create factory functions for consistent error creation across your application:
1// Error factory for validation errors
2export function createValidationError(
3 field: string,
4 value: unknown,
5 reason: string
6): TryError {
7 return createTryError(
8 'VALIDATION_ERROR',
9 `Validation failed for ${field}: ${reason}`,
10 { field, value, reason }
11 );
12}
13
14// Error factory for API errors
15export function createApiError(
16 endpoint: string,
17 status: number,
18 statusText: string
19): TryError {
20 return createTryError(
21 'API_ERROR',
22 `API request failed: ${status} ${statusText}`,
23 { endpoint, status, statusText }
24 );
25}
26
27// Error factory for database errors
28export function createDatabaseError(
29 operation: string,
30 table: string,
31 cause?: Error
32): TryError {
33 return createTryError(
34 'DATABASE_ERROR',
35 `Database ${operation} failed on table ${table}`,
36 { operation, table },
37 cause
38 );
39}
40
41// Usage
42const emailError = createValidationError(
43 'email',
44 'not-an-email',
45 'must contain @ symbol'
46);
47
48const apiError = createApiError('/api/users', 404, 'Not Found');
49
50const dbError = createDatabaseError('INSERT', 'users', originalError);
Error Matching and Handling
Use the source property to handle different types of errors:
1import { tryAsync, isTryError } from 'try-error';
2
3async function handleUserOperation(userId: string) {
4 const result = await tryAsync(() => fetchUser(userId));
5
6 if (isTryError(result)) {
7 switch (result.source) {
8 case 'NETWORK_ERROR':
9 console.error('Network issue:', result.message);
10 // Maybe retry the operation
11 break;
12
13 case 'VALIDATION_ERROR':
14 console.error('Invalid input:', result.message);
15 // Show user-friendly error message
16 break;
17
18 case 'AUTH_ERROR':
19 console.error('Authentication failed:', result.message);
20 // Redirect to login
21 break;
22
23 default:
24 console.error('Unexpected error:', result.message);
25 // Generic error handling
26 }
27
28 return null;
29 }
30
31 return result;
32}
33
34// You can also check error context
35function handleError(error: TryError) {
36 if (error.source === 'VALIDATION_ERROR' && error.context?.field === 'email') {
37 return 'Please enter a valid email address';
38 }
39
40 if (error.source === 'API_ERROR' && error.context?.status === 429) {
41 return 'Too many requests. Please try again later.';
42 }
43
44 return 'An unexpected error occurred';
45}
Best Practices
✅ Do
- • Use consistent error source naming (e.g., UPPER_SNAKE_CASE)
- • Include relevant context for debugging
- • Use error factories for consistency
- • Chain errors to preserve the original cause
- • Make error messages user-friendly when appropriate
- • Include actionable information in error context
❌ Don't
- • Include sensitive information in error messages or context
- • Use generic error messages without context
- • Create too many specific error types
- • Ignore the original error when creating custom errors
- • Put large objects in error context