# How OmniRoute Prevents Error Stack Exposure: A Complete Security Implementation

> OmniRoute prevents error stack exposure by centralizing error sanitization. Learn how its utilities stop raw stack traces and sensitive data from leaking to clients.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: deep-dive
- Published: 2026-08-26

---

**OmniRoute enforces Hard Rule #12 by centralizing error sanitization in [`open-sse/utils/error.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/utils/error.ts), ensuring no raw stack traces, absolute file paths, or sensitive credentials leak to clients through the `sanitizeErrorMessage` and `buildErrorBody` utilities.**

OmniRoute (diegosouzapw/OmniRoute) implements strict security controls to prevent **error stack exposure**, a critical vulnerability that can reveal server internals, file-system layouts, and sensitive data to attackers. The framework mandates Hard Rule #12, which requires that raw error messages and stack traces must never reach client responses. This article examines the centralized sanitization architecture that enforces this rule across all API routes, Server-Sent Events (SSE) streams, and Model Context Protocol (MCP) server endpoints.

## Centralized Error Sanitization Architecture

All error handling in OmniRoute funnels through a single source of truth located in [`open-sse/utils/error.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/utils/error.ts). This module exports two primary functions that transform dangerous raw errors into safe, client-ready messages.

### The sanitizeErrorMessage Function

The **`sanitizeErrorMessage(message)`** function accepts any input value—whether a string, `Error` object, `undefined`, or otherwise—and returns a sanitized, single-line string. According to the source code in `diegosouzapw/OmniRoute`, this function implements four critical security behaviors:

- **Stack trace truncation**: The function keeps only the first line of any input, automatically discarding subsequent stack-trace lines that would reveal internal call hierarchies.
- **Path redaction**: It identifies and removes absolute file-system paths (such as `/home/user/project/file.ts:10` or `C:\Users\admin\app\index.js`) and replaces them with the placeholder `<path>`.
- **Credential scrubbing**: The function redacts sensitive fragments including Bearer tokens, JSON fields like `apiKey`, `access_token`, and `client_secret`, plus data-URL images that might contain embedded secrets.
- **Input normalization**: Non-string inputs are handled safely—`undefined` and `null` become empty strings, numbers convert to their string representation, and `Error` objects reduce to `"Error: <message>"`.

Additionally, the implementation includes a lightweight regular-expression guard that prevents pathologically long inputs from triggering ReDoS (Regular Expression Denial of Service) slowdowns, ensuring the sanitization remains performant under adversarial conditions.

### The buildErrorBody Wrapper

The **`buildErrorBody(error)`** function consumes the output of `sanitizeErrorMessage` and wraps it into a consistent JSON error payload for HTTP and SSE responses. All API routes import this helper and return standardized error objects using `new Response(buildErrorBody(err))`. This guarantees a uniform error format across the entire application surface while maintaining the security boundaries established by the sanitization layer.

## Enforced Usage Across the Codebase

OmniRoute treats error sanitization as a mandatory pattern rather than an optional convention. Every route, handler, executor, and utility that might throw an exception must catch the error and process it through either `sanitizeErrorMessage` directly or via `buildErrorBody`. The codebase enforces this through unit tests located in [`tests/unit/rule12-error-sanitization-sweep.test.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/tests/unit/rule12-error-sanitization-sweep.test.ts), which scan source files to verify the correct import and call patterns exist.

The sanitization logic appears in the following key components:

| Component | Implementation File |
|-----------|-------------------|
| API route handlers | [`src/app/api/v1/chat/completions/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/v1/chat/completions/route.ts) |
| SSE request handlers | [`open-sse/handlers/chatCore.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/handlers/chatCore.ts) |
| MCP server | `open-sse/mcp-server/server.cjs` |
| Authentication middleware | [`src/sse/services/auth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/sse/services/auth.ts) |
| Credential retry logic | [`src/sse/services/imageCredentialRetry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/sse/services/imageCredentialRetry.ts) |
| General utility wrappers | [`src/shared/utils/fetchError.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/utils/fetchError.ts) |

All imports resolve to the same [`open-sse/utils/error.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/utils/error.ts) implementation, ensuring **no raw stack trace or file path can leak** through any public endpoint, including Next.js API routes, SSE streaming layers, MCP servers, or embedded service endpoints.

## Implementation Examples

The following patterns demonstrate how OmniRoute integrates error sanitization into different architectural layers.

### Basic Sanitization in API Routes

```typescript
import { sanitizeErrorMessage, buildErrorBody } from "@omniroute/open-sse/utils/error";

export async function GET(req: Request) {
  try {
    // …process request…
  } catch (err) {
    // The raw error might contain a stack trace and absolute paths.
    const safe = sanitizeErrorMessage(err);
    // Build a JSON payload that the client receives.
    return new Response(buildErrorBody(safe), { status: 500 });
  }
}

```

### Error Handling in SSE Streams

```typescript
import { sanitizeErrorMessage } from "@omniroute/open-sse/utils/error";

export async function streamChat(req: Request) {
  const encoder = new TextEncoder();
  const stream = new ReadableStream({
    async start(controller) {
      try {
        // …stream data…
      } catch (err) {
        const safeMsg = sanitizeErrorMessage(err);
        controller.enqueue(encoder.encode(`event: error\ndata: ${safeMsg}\n\n`));
        controller.close();
      }
    },
  });
  return new Response(stream, { headers: { "Content-Type": "text/event-stream" } });
}

```

### Low-Level Utility Integration

```typescript
import { sanitizeErrorMessage } from "@omniroute/open-sse/utils/error";

export async function fetchWithSafeError(url: string) {
  try {
    const res = await fetch(url);
    if (!res.ok) throw new Error(`Upstream ${res.status}`);
    return await res.json();
  } catch (e) {
    // Guarantees that no stack trace reaches the caller.
    throw new Error(sanitizeErrorMessage(e));
  }
}

```

## Summary

- **Centralized sanitization**: All error handling flows through [`open-sse/utils/error.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/utils/error.ts), specifically the `sanitizeErrorMessage` and `buildErrorBody` functions.
- **Multi-layered protection**: The system removes stack traces, replaces absolute paths with `<path>`, and redacts credentials like tokens and API keys.
- **Universal enforcement**: Hard Rule #12 applies to API routes, SSE handlers, MCP servers, and middleware, verified by automated unit tests in [`tests/unit/rule12-error-sanitization-sweep.test.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/tests/unit/rule12-error-sanitization-sweep.test.ts).
- **Input resilience**: The sanitization handles arbitrary input types safely and includes ReDoS protection against maliciously crafted error messages.

## Frequently Asked Questions

### What constitutes error stack exposure and why is it dangerous?

Error stack exposure occurs when server-side applications return raw error messages, stack traces, or absolute file paths to clients. This information leakage reveals internal code structure, server file-system layouts, and potential vulnerabilities that attackers can exploit to craft targeted attacks against the application.

### How does sanitizeErrorMessage handle non-string error inputs?

The `sanitizeErrorMessage` function normalizes all input types: `undefined` and `null` become empty strings, numbers convert to their string representation, and `Error` objects reduce to a safe `"Error: <message>"` format without their stack property. This ensures consistent, safe output regardless of what type of value was thrown or caught.

### Where is OmniRoute's error sanitization logic centralized?

All error sanitization logic resides in [`open-sse/utils/error.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/utils/error.ts) within the `diegosouzapw/OmniRoute` repository. This file exports both `sanitizeErrorMessage` for cleaning raw error content and `buildErrorBody` for constructing standardized JSON error responses that are safe to transmit to clients.

### How does OmniRoute ensure developers consistently use error sanitization?

OmniRoute enforces error sanitization through mandatory unit tests located in [`tests/unit/rule12-error-sanitization-sweep.test.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/tests/unit/rule12-error-sanitization-sweep.test.ts). These tests programmatically scan the source codebase to verify that every error import and catch block correctly invokes `sanitizeErrorMessage` or `buildErrorBody`, preventing accidental deployment of routes that might leak sensitive error details.