Error Handling
VentureKit provides structured error classes that automatically map to HTTP status codes and JSON error responses. Throw any VentureError subclass in your handler and the error boundary middleware handles the rest.
Error Classes
Section titled “Error Classes”| Class | Status | Code | Use Case |
|---|---|---|---|
BadRequestError | 400 | BAD_REQUEST | Invalid input |
UnauthorizedError | 401 | UNAUTHORIZED | Missing/invalid authentication |
ForbiddenError | 403 | FORBIDDEN | Authenticated but not allowed |
NotFoundError | 404 | NOT_FOUND | Resource doesn’t exist |
ConflictError | 409 | CONFLICT | State conflict or duplicate |
ValidationError | 422 | VALIDATION_ERROR | Field validation failed |
RateLimitError | 429 | RATE_LIMITED | Too many requests |
InternalError | 500 | INTERNAL_ERROR | Unexpected server error |
ServiceUnavailableError | 503 | SERVICE_UNAVAILABLE | Dependency failure |
import { handler, NotFoundError, BadRequestError } from '@venturekit/runtime';
export const main = handler(async (body, ctx, logger) => { if (!body.title) { throw new BadRequestError('Title is required'); }
const task = await findTask(body.id); if (!task) { throw new NotFoundError('Task', body.id); }
return task;}, { scopes: ['tasks.read'] });Error Response Format
Section titled “Error Response Format”All errors produce a consistent JSON response:
{ "error": { "code": "NOT_FOUND", "message": "Task '123' not found", "details": { "resource": "Task", "id": "123" } }}Detailed Examples
Section titled “Detailed Examples”Validation Error
Section titled “Validation Error”import { ValidationError } from '@venturekit/runtime';
throw new ValidationError('Validation failed', { title: ['Title is required', 'Title must be at least 3 characters'], email: ['Invalid email format'],});Response:
{ "error": { "code": "VALIDATION_ERROR", "message": "Validation failed", "details": { "fields": { "title": ["Title is required", "Title must be at least 3 characters"], "email": ["Invalid email format"] } } }}Rate Limit Error
Section titled “Rate Limit Error”import { RateLimitError } from '@venturekit/runtime';
throw new RateLimitError(60); // Retry after 60 secondsService Unavailable
Section titled “Service Unavailable”import { ServiceUnavailableError } from '@venturekit/runtime';
throw new ServiceUnavailableError('Database');// → "Database is currently unavailable" (503)Custom Errors
Section titled “Custom Errors”Extend VentureError for domain-specific errors:
import { VentureError } from '@venturekit/runtime';
class PaymentRequiredError extends VentureError { constructor(message: string = 'Payment required') { super('PAYMENT_REQUIRED', message, 402); this.name = 'PaymentRequiredError'; }}Type Guard
Section titled “Type Guard”Check if an error is a VentureKit error:
import { isVentureError } from '@venturekit/runtime';
try { await doSomething();} catch (error) { if (isVentureError(error)) { logger.warn('Known error', { code: error.code, status: error.statusCode }); } else { logger.error('Unexpected error', { error }); }}Automatic Error Handling
Section titled “Automatic Error Handling”The handler() function automatically:
- Wraps your code in an error boundary middleware
- Catches any thrown error
- If it’s a
VentureError, returns the appropriate HTTP status and JSON body - If it’s an unknown error, returns
500 Internal Server Errorwith a safe message - Logs the error with the request context