Error Handling
Demonstrates how errors thrown in worker handlers propagate back to the host, including error messages and proper cleanup.
Error Handling Example
Demonstrates error propagation from worker to host.
Overview
This example shows:
- How errors thrown in worker handlers propagate back to the host
- Proper error handling with try/catch
- Error messages are preserved across process boundaries
- Shared message definitions between host and worker
Files
Shared Message Definitions
First, define the message types in a shared file that both host and worker import:
messages.ts
/**
* Shared message definitions for the error-handling example
*
* This file is imported by both the host and worker to ensure
* type safety and avoid duplication.
*/
import { DefineMessages } from 'isolated-workers';
/**
* Message types for the division example
*/
export type Messages = DefineMessages<{
divide: {
payload: { a: number; b: number };
result: { result: number };
};
}>;
Host
The host imports the message types and handles both success and error cases:
host.ts
/**
* Error Handling Example - Host (Client) Side
*
* Demonstrates error propagation from worker to host.
*/
import { createWorker } from 'isolated-workers';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import type { Messages } from './messages.js';
const __dirname = dirname(fileURLToPath(import.meta.url));
async function main() {
console.log('=== Error Handling Example ===\n');
const worker = await createWorker<Messages>({
script: join(__dirname, 'worker.ts'),
timeout: 10000,
});
console.log(`Worker spawned with PID: ${worker.pid}\n`);
// Test 1: Successful division
console.log('Test 1: 10 / 2');
try {
const result = await worker.send('divide', { a: 10, b: 2 });
console.log('Result:', result.result, '\n');
} catch (err) {
console.error('Unexpected error:', (err as Error).message, '\n');
}
// Test 2: Division by zero (should error)
console.log('Test 2: 10 / 0 (should error)');
try {
await worker.send('divide', { a: 10, b: 0 });
console.log('ERROR: Should have thrown!\n');
} catch (err) {
console.log('Caught expected error:', (err as Error).message, '\n');
}
// Test 3: Cleanup
console.log('Test 3: Cleanup');
await worker.close();
console.log('Worker closed successfully\n');
console.log('=== All tests passed ===');
}
main().catch((err) => {
console.error('Host error:', err);
process.exit(1);
});
Worker
The worker imports the same message types and throws errors for invalid operations:
worker.ts
/**
* Error Handling Example - Worker (Server) Side
*
* Demonstrates error throwing and propagation.
*/
import { startWorkerServer, Handlers } from 'isolated-workers';
import type { Messages } from './messages.js';
// Define handlers for incoming messages with proper typing
const handlers: Handlers<Messages> = {
divide: ({ a, b }) => {
console.log(`Worker: dividing ${a} / ${b}`);
if (b === 0) {
throw new Error('Division by zero');
}
return { result: a / b };
},
};
async function main() {
console.log('Worker: starting error-handling demo worker');
await startWorkerServer(handlers);
console.log('Worker: ready');
process.on('SIGTERM', () => {
console.log('Worker: shutting down');
process.exit(0);
});
}
main().catch((err) => {
console.error('Worker error:', err);
process.exit(1);
});
Running
cd examples && pnpm run:error-handling
Key Concepts
- Shared Types: Message definitions in
messages.tsimported by both sides - Error Propagation: Errors thrown in worker are serialized and re-thrown in host
- Type Safety: Full TypeScript inference from shared message definitions
Running the Example
Run the example
bash
pnpm run:error-handling