How OmniRoute Handles Error Handling and Response Sanitization
OmniRoute centralizes every error path through the open-sse/utils/error.ts module, where sanitizeErrorMessage and buildErrorBody strip sensitive internals and emit a safe, structured JSON payload before any response reaches the client.
The diegosouzapw/OmniRoute repository treats error leakage as a critical security risk. Its approach to error handling and response sanitization relies on a small set of tightly controlled utility functions that remove stack traces and absolute file paths from all non-streaming and streaming responses.
Core Sanitization Utilities in open-sse/utils/error.ts
The error pipeline is built on two primary helpers exported from open-sse/utils/error.ts.
sanitizeErrorMessage
sanitizeErrorMessage truncates an error down to its first line and scrubs stack traces, absolute paths, and any other potentially sensitive metadata. According to the OmniRoute source code, every catch block that returns an error to the client must call this function before exposing any text.
buildErrorBody and buildStreamErrorChunks
buildErrorBody accepts an HTTP status code and a sanitized message, then returns a JSON object that conforms to the API error contract: { error: { message, type?, code? } }. For streaming endpoints, buildStreamErrorChunks performs the same transformation but packages the result into Claude-compatible SSE error frames.
The Four-Step Error Handling Workflow
OmniRoute enforces a uniform pattern across all route handlers and stream constructors:
- Catch the exception inside the route or service.
- Sanitize the error via
sanitizeErrorMessage(err)orsanitizeErrorMessage(err?.message). - Build a structured payload using
buildErrorBody(status, sanitizedMessage)or SSE-specific helpers. - Return the safe payload as the HTTP response, or enqueue it into the SSE stream.
Sanitizing Errors in Standard HTTP Routes
Below is the typical pattern found in Next.js API routes such as src/app/api/playground/presets/route.ts.
// src/app/api/playground/presets/route.ts
import { buildErrorBody, sanitizeErrorMessage } from "@omniroute/open-sse/utils/error.ts";
export async function POST(req: Request) {
try {
// normal handler logic
} catch (err) {
const safeMsg = sanitizeErrorMessage(err);
return new Response(JSON.stringify(buildErrorBody(500, safeMsg)), {
status: 500,
headers: { "Content-Type": "application/json" },
});
}
}
In this flow, sanitizeErrorMessage prevents raw Error objects from reaching the client, while buildErrorBody guarantees a consistent JSON envelope.
Handling Errors in SSE Streams
Streaming endpoints in OmniRoute introduce additional complexity because errors must be emitted as SSE events rather than plain JSON responses. The repository solves this in open-sse/handlers/chatCore.ts through createDisconnectAwareStream.
Upstream Error Conversion
When an upstream provider returns an error during a chat completion stream, the handler converts it into a sanitized SSE chunk as shown in this excerpt:
// open-sse/handlers/chatCore.ts
import { sanitizeErrorMessage, buildStreamErrorChunks } from "./utils/error.ts";
function handleUpstreamError(upstreamError: Error) {
const safeMsg = sanitizeErrorMessage(upstreamError.message);
// For Claude-compatible streams:
return buildStreamErrorChunks(safeMsg, 502, null);
}
The createDisconnectAwareStream Controller
For generic SSE streams, createDisconnectAwareStream detects upstream failures, applies sanitizeErrorMessage, and emits an event: error frame followed by the sanitized payload. The implementation also sends a terminal event: message_stop frame for Claude-compatible streams so clients receive a clean close even after an error.
// open-sse/handlers/chatCore.ts
function createDisconnectAwareStream(controller) {
controller.error = (upstreamError) => {
const safeMsg = sanitizeErrorMessage(upstreamError.message);
controller.enqueue(
encodeSseEvent("error", { type: "server_error", message: safeMsg })
);
// close stream cleanly
};
}
This ensures that no raw stack trace or file system path ever leaks to the client, satisfying Hard Rule #12 as implemented in the OmniRoute source code.
Enforcement and Automated Testing
Sanitization is not merely a convention; it is enforced by the test suite. The file tests/unit/rule12-error-sanitization-sweep.test.ts contains unit tests that verify every error path invokes the sanitizer. Additionally, lint-time checks confirm that source files import sanitizeErrorMessage wherever catch blocks return errors to clients.
Summary
- OmniRoute centralizes error handling in
open-sse/utils/error.ts. sanitizeErrorMessagestrips stack traces and file paths, keeping only the first line of the error.buildErrorBodywraps sanitized messages into{ error: { message, type?, code? } }.- For SSE streams,
buildStreamErrorChunksandcreateDisconnectAwareStreamemit sanitizedevent: errorframes. - Hard Rule #12 is enforced by unit tests in
tests/unit/rule12-error-sanitization-sweep.test.tsand lint checks that require the sanitizer import.
Frequently Asked Questions
What is Hard Rule #12 in OmniRoute?
Hard Rule #12 prohibits the exposure of raw error objects to API consumers. As implemented in diegosouzapw/OmniRoute, this means every caught exception must pass through sanitizeErrorMessage before being serialized into an HTTP or SSE response.
How does OmniRoute prevent stack traces from leaking in SSE streams?
OmniRoute uses createDisconnectAwareStream in open-sse/handlers/chatCore.ts to intercept upstream errors. It calls sanitizeErrorMessage on the error text and emits an SSE event: error frame containing only the sanitized type, code, and message, ensuring internal stack details never reach the client.
What is the difference between buildErrorBody and buildStreamErrorChunks?
buildErrorBody generates a static JSON object for standard REST responses, while buildStreamErrorChunks formats a sanitized message into Claude-compatible SSE data frames. Both utilities use the same underlying sanitizer but target different transport protocols.
Where are OmniRoute's sanitization rules enforced beyond runtime?
Beyond runtime logic, OmniRoute enforces sanitization through tests/unit/rule12-error-sanitization-sweep.test.ts, which acts as a regression suite for every error path. The project also runs lint-time checks that flag any source file missing the required sanitizeErrorMessage import where catch blocks are present.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →