Zuplo
Error Handling

Runtime Errors

Zuplo provides specialized error classes for handling runtime and configuration errors in your API gateway.

RuntimeError

The RuntimeError class extends the standard JavaScript Error class and provides additional functionality for including extension members in error responses.

Constructor

new RuntimeError(message: string, options?: ErrorOptions) new RuntimeError( info: { message: string; extensionMembers?: Record<string, unknown> }, options?: ErrorOptions )
ts

Creates a new runtime error with optional extension data.

  • message - The error message
  • info - Object containing message and optional extension members
  • options - Standard error options (e.g., cause)

Properties

extensionMembers

Additional data included with the error for context and debugging.

extensionMembers?: Record<string, unknown>
ts

Example

import { RuntimeError, ZuploContext, ZuploRequest } from "@zuplo/runtime"; export default async function handler( request: ZuploRequest, context: ZuploContext, ) { try { // Some operation that might fail const result = await riskyOperation(); return new Response(JSON.stringify(result)); } catch (error) { // Throw a RuntimeError with additional context throw new RuntimeError( { message: "Failed to process request", extensionMembers: { requestId: context.requestId, operation: "riskyOperation", timestamp: new Date().toISOString(), }, }, { cause: error }, ); } }
ts

ConfigurationError

The ConfigurationError class extends RuntimeError and is specifically designed for configuration-related errors.

Constructor

new ConfigurationError(message: string, options?: ErrorOptions)
ts

Creates a new configuration error.

  • message - The error message describing the configuration issue
  • options - Standard error options

Example

import { ConfigurationError, ZuploContext, ZuploRequest, environment, } from "@zuplo/runtime"; export default async function handler( request: ZuploRequest, context: ZuploContext, ) { const apiKey = environment.EXTERNAL_API_KEY; if (!apiKey) { throw new ConfigurationError( "EXTERNAL_API_KEY environment variable is not configured", ); } const maxRetries = parseInt(environment.MAX_RETRIES || "3"); if (isNaN(maxRetries) || maxRetries < 1) { throw new ConfigurationError("MAX_RETRIES must be a positive integer"); } // Continue with properly configured values return fetch("https://api.example.com", { headers: { "X-API-Key": apiKey }, }); }
ts

Error Handling Best Practices

1. Use Specific Error Types

import { ConfigurationError, RuntimeError } from "@zuplo/runtime"; // For configuration issues if (!config.isValid()) { throw new ConfigurationError( "Invalid configuration: missing required fields", ); } // for runtime issues if (response.status === 503) { throw new RuntimeError({ message: "Service temporarily unavailable", extensionMembers: { retryAfter: response.headers.get("Retry-After"), service: "external-api", }, }); }
ts

2. Include Helpful Context

throw new RuntimeError( { message: "Database query failed", extensionMembers: { query: "SELECT * FROM users WHERE id = ?", parameters: [userId], errorCode: "DB_CONNECTION_TIMEOUT", suggestion: "Check database connection settings", }, }, { cause: originalError }, );
ts

3. Use Error Boundaries in Policies

import { RuntimeError, ZuploContext, ZuploRequest } from "@zuplo/runtime"; export default async function customPolicy( request: ZuploRequest, context: ZuploContext, options: any, policyName: string, ) { try { // Policy logic here return request; } catch (error) { // Log the error context.log.error("Policy execution failed", { policyName, error: error instanceof Error ? error.message : String(error), }); // Re-throw as RuntimeError with context throw new RuntimeError( { message: `Policy '${policyName}' failed to execute`, extensionMembers: { policyName, originalError: error instanceof Error ? error.message : String(error), }, }, { cause: error }, ); } }
ts

Integration with Problem Details

When using HttpProblems, errors can be automatically converted to RFC 7807 Problem Details responses:

import { RuntimeError, HttpProblems, ZuploContext, ZuploRequest, } from "@zuplo/runtime"; export default async function handler( request: ZuploRequest, context: ZuploContext, ) { try { // Your logic here } catch (error) { if (error instanceof ConfigurationError) { return HttpProblems.internalServerError(request, context, { detail: error.message, instance: `/errors/${context.requestId}`, }); } if (error instanceof RuntimeError && error.extensionMembers) { return HttpProblems.internalServerError(request, context, { detail: error.message, ...error.extensionMembers, }); } // Default error response return HttpProblems.internalServerError(request, context); } }
ts

See Also