OmniRoute Error Sanitization and Message Handling Pattern Explained

OmniRoute implements a centralized error-handling pipeline that prevents stack traces, file paths, and credentials from ever reaching clients by funneling all errors through a single sanitization layer.

The OmniRoute project, maintained at diegosouzapw/OmniRoute, enforces strict security guarantees for error responses across its entire API surface. Every handler, SSE stream writer, and combo-diagnostics module delegates error construction to a dedicated utilities layer. This article examines the implementation in open-sse/utils/error.ts and demonstrates how the pattern achieves defense-in-depth for production deployments.

Core Sanitization Functions

Three primary functions form the foundation of OmniRoute's error sanitization. Each operates at a different level of abstraction, from simple string cleaning to full payload reconstruction.

sanitizeErrorMessage

The sanitizeErrorMessage(message) function applies the first line of defense. Located at open-sse/utils/error.ts#L63-L74, it performs these operations in sequence:

  • Truncates messages exceeding length limits
  • Tokenizes the first line to drop stack trace continuations
  • Replaces absolute POSIX and Windows paths with the literal <path>
  • Redacts data URLs, authentication headers, and key-like tokens

This function is universally applied to every user-facing error string before transmission.

sanitizeUpstreamDetails

Upstream providers may return arbitrary JSON payloads containing sensitive metadata. The sanitizeUpstreamDetails(value, depth = 0) function at open-sse/utils/error.ts#L88-L104 recursively sanitizes these responses with configurable guards:

  • Depth limitation: Hard stops at MAX_DEPTH = 4
  • Key blocking: Drops properties matching the BLOCKED_KEYS credential regex
  • String sanitization: Runs all string values through sanitizeErrorMessage
  • Array capping: Limits arrays to 32 elements

buildErrorBody

The buildErrorBody(statusCode, message, upstreamDetails?, classification?) function at open-sse/utils/error.ts#L121-L146 constructs the final response structure. It:

  1. Looks up default type and code values from HTTP status via getErrorInfo
  2. Sanitizes the supplied message
  3. Optionally attaches cleaned upstream details under upstream_details
  4. Returns an OpenAI-compatible schema: { error: { message, type?, code? }, upstream_details? }

High-Level Error Response Helpers

Four exported helpers abstract the core functions for different response contexts.

Helper Purpose Source Location
errorResponse(statusCode, message) JSON responses from non-streaming handlers open-sse/utils/error.ts#L443-L50
writeStreamError(writer, statusCode, message) SSE stream error events open-sse/utils/error.ts#L58-L66
errorResponseWithComboDiagnostics(status, msg, diagnostics, opts) Combo routing failures with sanitized diagnostic headers open-sse/utils/error.ts#L86-L131
createErrorResult(...) Internal pipeline representation carrying raw message for classification while exposing sanitized response open-sse/utils/error.ts#L527-L588

The errorResponseWithComboDiagnostics helper deserves special attention. When combo routing terminates, it builds a response that simultaneously:

  • Contains the standard sanitized error body
  • Embeds a sanitized diagnostic trace in custom x-omniroute-* headers
  • Adds the same trace under diagnostics in the JSON payload
  • Optionally includes recovery hints via x-omniroute-recovery-* headers

Error Handling in the Request Pipeline

All HTTP API entry points eventually delegate to these helpers. The following excerpts from handler files demonstrate consistent application.

Chat Handler Validation

// src/sse/handlers/chat.ts
import { errorResponse } from "@omniroute/open-sse/utils/error.ts";

if (!model) return errorResponse(HTTP_STATUS.BAD_REQUEST, "Missing model");

Line 454 of this file shows validation failures funneled through the sanitization layer.

Reasoning Routing Handler

// src/sse/handlers/reasoningRouting.ts
return errorResponse(HTTP_STATUS.SERVICE_UNAVAILABLE, msg);

Upstream failures receive identical treatment.

SSE Streaming Errors

// src/sse/handlers/chatHelpers.ts
await writeStreamError(writer, HTTP_STATUS.UNAUTHORIZED, message);

Streaming contexts use writeStreamError to emit clean JSON payloads directly into the SSE stream.

These patterns repeat across src/sse/handlers/*.ts. Search for errorResponse( imports to locate all usage sites.

Specialized Error Types

OmniRoute provides domain-specific helpers for operational scenarios.

Provider Circuit-Breaker

The providerCircuitOpenResponse function returns HTTP 503 with:

  • Retry-After header for client backoff
  • Machine-readable code: "provider_circuit_open"

Model Cooldown

The modelCooldownResponse function returns HTTP 429 with:

  • Structured model_cooldown body
  • Retry-After header indicating cooldown expiration

Both helpers internally invoke sanitizeErrorMessage, maintaining the same security guarantees.

Implementation Examples

Basic API Route Error

import { errorResponse } from "@omniroute/open-sse/utils/error.ts";

export async function POST(req: Request) {
  const body = await req.json();
  if (!body.prompt) {
    return errorResponse(400, "Missing required field: prompt");
  }
  // Normal processing continues...
}

The raw message "Missing required field: prompt" passes through sanitizeErrorMessage before reaching the client.

Streaming Context Error

import { writeStreamError } from "@omniroute/open-sse/utils/error.ts";

async function streamResponse(writer: WritableStreamDefaultWriter<Uint8Array>) {
  try {
    const data = await fetchRemote();
    // ...stream data...
  } catch (e) {
    await writeStreamError(writer, 502, e);
  }
}

The raw exception e is never serialized directly—only its sanitized representation appears in the stream.

Combo Routing with Diagnostics

import { errorResponseWithComboDiagnostics } from "@omniroute/open-sse/utils/error.ts";

const diagnostics = {
  poolSize: 12,
  attempted: 5,
  excluded: [{ provider: "openai", model: "gpt-4o-mini", reason: "rate_limit" }],
  attemptOrder: [{ provider: "anthropic", model: "claude-3" }],
  terminalReason: "all_candidates_exhausted",
  recovery: { action: "try-auto", next_step: "Switch to auto-combo mode" },
};

return errorResponseWithComboDiagnostics(503, "Combo exhausted", diagnostics);

Diagnostic objects are recursively sanitized before appearing in headers or JSON payloads.

Key Files Reference

File Role
open-sse/utils/error.ts Central sanitization and response factory—the core of the pattern
src/shared/utils/apiResponse.ts Higher-level management route responses (delegates to streaming utils for sanitization)
src/sse/handlers/chat.ts Handler demonstrating errorResponse usage
src/sse/handlers/chatHelpers.ts SSE streaming with writeStreamError
src/sse/handlers/reasoningRouting.ts Upstream failure handling
tests/unit/combo/recovery-hint.test.ts End-to-end validation of header sanitization

Summary

  • Single source of truth: All errors route through open-sse/utils/error.ts
  • Layered sanitization: String cleaning → recursive payload cleaning → structured response assembly
  • No leakage guarantee: Stack traces, paths, credentials, and upstream internals never reach clients
  • OpenAI compatibility: Standardized error schema eases client integration
  • Operational visibility: Diagnostic headers and recovery hints maintain debugging utility without compromising security

Frequently Asked Questions

How does OmniRoute prevent credential leakage in error messages?

OmniRoute applies sanitizeErrorMessage to every user-facing string. This function redacts data URLs, authentication headers, and key-like tokens using pattern matching. Additionally, sanitizeUpstreamDetails drops any JSON property matching the BLOCKED_KEYS regex before serialization.

What is the maximum recursion depth for upstream error sanitization?

The sanitizeUpstreamDetails function enforces MAX_DEPTH = 4 to prevent performance degradation on deeply nested upstream responses. Arrays are additionally capped at 32 elements, and all strings undergo the standard sanitization pass.

Can I include debugging information in production error responses?

Yes—use errorResponseWithComboDiagnostics to attach sanitized diagnostic traces. These appear in both custom x-omniroute-* headers and the JSON payload under diagnostics. The same sanitization rules apply, ensuring no sensitive data escapes.

Does OmniRoute support custom error classifications?

The buildErrorBody function accepts an optional classification parameter that feeds into the error type/code lookup. Specialized helpers like providerCircuitOpenResponse and modelCooldownResponse demonstrate predefined classifications for operational scenarios.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →