# How to Debug OmniRoute: A Layered Approach to Troubleshooting LLM Router Issues

> Debug OmniRoute issues effectively by enabling debug logging and tracing requests through its nine-layer architecture using request IDs to correlate logs across all components.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-07-24

---

**To debug OmniRoute, enable `APP_LOG_LEVEL=debug` and trace requests through the nine-layer architecture—from API entry points to the MCP server—using request IDs to correlate logs across the Context Manager, Combo Routing engine, and Executor layers.**

OmniRoute is a complex, modular router that stitches together dozens of LLM providers, a streaming engine, combo-routing logic, guardrails, and a full-stack UI. Because many components run in different processes (Next.js API routes, the `open-sse` streaming workspace, the MCP server, and the MITM proxy), successful debugging requires a systematic approach that leverages environment variables, UI toggles, and specific source files in the `diegosouzapw/OmniRoute` repository.

## The Nine Layers of OmniRoute Debugging

OmniRoute's architecture spans nine distinct layers. When you debug OmniRoute issues, work through these layers from the request entry point down to persistence and artifacts.

### 1. Request-Level Logs

Every request generates a UUID (e.g., `req=xxxx`) logged in `src/app/api/v1/**/route.ts` files such as [`chat/completions/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/chat/completions/route.ts). These logs capture timestamps, the selected provider and model, and sanitized auth headers.

To enable detailed output, set `APP_LOG_LEVEL=debug` in your environment or toggle **Debug Mode** in the UI under *Settings → Advanced*.

### 2. Context Manager

The per-request context object holds metadata including the request ID, provider, combo configuration, and rate-limit info. Located in [`open-sse/contextManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/contextManager.ts), this layer automatically logs context creation when `APP_LOG_LEVEL` is set to `debug`.

### 3. Combo Routing

This layer handles target resolution, strategy selection, and fallback decisions. The key function is `resolveComboTargets()` in [`open-sse/services/combo.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/services/combo.ts). Enable the **Traffic Inspector** tool in the Dashboard to see the ordered list of resolved targets, or toggle `debugMode` to surface these logs.

### 4. Translator and Transformer

Request format conversion between OpenAI, Anthropic, Gemini, and other formats happens in `open-sse/translator/` and `open-sse/transformer/`. Use the **Dashboard → Translator** playground to view raw upstream requests and final downstream responses for debugging translation mismatches.

### 5. Executor

Provider-specific request building, header construction, retries, and proxy routing occur in `open-sse/executors/` (e.g., [`default.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/default.ts), [`cursor.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/cursor.ts)). Set `OMNIROUTE_PROXY_FETCH_DEBUG=true` to emit `[ProxyFetch]` debug lines for every proxy-relay call.

### 6. Guardrails

Prompt-injection guards, PII redaction, and tool-source diagnostics reside in `src/lib/guardrails/`. Enable "Tool-source diagnostics" in **Dashboard → Settings → Debug** to see which module originated each tool definition. Guardrail modules write concise `[Guardrail]` lines when modifying or blocking payloads.

### 7. MCP and A2A

Tool invocation logs, scope checks, and JSON-RPC flow are managed in `open-sse/mcp-server/` and `src/lib/a2a/`. The MCP server writes per-tool audit rows to the SQLite `mcp_audit` table, viewable via the **Traffic Inspector** UI.

### 8. Database and Persistence

Call-log trimming, quota snapshots, and compression stats are handled in `src/lib/db/` modules. If you encounter "`deleteCallLogRowsByIds` too many SQL variables" errors, note that the log-trimmer in [`src/lib/db/callLogs.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/callLogs.ts) now chunks deletions automatically to avoid SQLite limits.

### 9. File-System Artifacts

Legacy log files in `${DATA_DIR}/log.txt` and `call_logs/` directories (managed by [`src/lib/db/healthCheck.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/healthCheck.ts)) contain raw request/response dumps when `APP_LOG_LEVEL=debug` is enabled for backward compatibility.

## Step-by-Step Debugging Workflow

Follow this systematic workflow to diagnose issues in OmniRoute:

1. **Reproduce the issue locally** by running the dev server with `npm run dev`.

2. **Identify the request ID** from the first line of every request log, which contains a UUID like `req=xxxx`.

3. **Trace through the pipeline** by grepping the request ID in logs to observe:
   - Context creation in `contextManager`
   - Combo resolution via [`combo.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/combo.ts)
   - Translator input/output in [`translator/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/translator/index.ts)
   - Executor calls in `executors/*`
   - Final SSE stream or JSON response

4. **Enable fine-grained debugging**:
   - Set `APP_LOG_LEVEL=debug` for all internal `pino` logs
   - Set `OMNIROUTE_PROXY_FETCH_DEBUG=true` for low-level fetch diagnostics
   - Activate the UI "Debug Mode" toggle to reveal hidden sidebar panels (Translator, Playground, Search Tools)

5. **Use Dashboard tools**:
   - **Translator Playground**: Paste request payloads to see exact upstream requests and edit them
   - **Traffic Inspector**: Visualizes tool calls, combo targets, and proxy hops
   - **Live Monitor**: Streams raw SSE chunks for real-time inspection

6. **Check guardrail logs** for `[Guardrail]` entries indicating payload modifications.

7. **Inspect the database** by running tests like `npm run typecheck:core && node --import tsx/esm --test tests/unit/call-log-trim-sql-vars-5217.test.ts` to verify SQLite bound-param limits are not exceeded.

## Common Issues and Quick Fixes

| Symptom | Likely Cause | Quick Fix |
|---------|--------------|-----------|
| **Empty response body** | Provider returned no data but executor suppressed the error | Set `APP_LOG_LEVEL=debug` and look for `[Executor] response empty` lines |
| **Tool list truncated** | Legacy hard-coded `MAX_TOOLS_LIMIT=128` | Update to the latest version which detects Opencode clients and only truncates when provider-specific limits are known (see [`chatcore/tools.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/chatcore/tools.ts)) |
| **Missing proxy information** | `[ProxyEgress]` logged `proxy=direct` incorrectly | Ensure proxy pool is configured and `APP_LOG_LEVEL=debug` is set to see actual proxy names via AsyncLocalStorage-threaded context |
| **SQLite "Too many SQL variables"** | `deleteCallLogRowsByIds` attempted single `IN (...)` with >999 IDs | The truncation logic now batches deletions (≤500 per statement) automatically |
| **Unexpected guardrail redaction** | `PII_REDACTION_ENABLED` or `PII_RESPONSE_SANITIZATION` set to `true` | Verify these env vars are unset unless intentional |
| **MCP tool-routing confusion** | Tool-source diagnostics disabled | Enable the "Tool-source diagnostics" toggle to label each tool with its originating module |

## Essential Debug Commands and Configuration

Enable full debug output from the command line:

```bash
export APP_LOG_LEVEL=debug
export OMNIROUTE_PROXY_FETCH_DEBUG=true
npm run dev

```

Fetch a request's log by ID using Unix grep:

```bash
grep -R "req=123e4567-e89b-12d3-a456-426614174000" logs/

```

Programmatically trace requests in Node.js:

```javascript
import { v4 as uuidv4 } from "uuid";

const requestId = uuidv4(); // pass this header downstream
fetch("http://localhost:3000/api/v1/chat/completions", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-omniroute-request-id": requestId,
  },
  body: JSON.stringify({ model: "gpt-4o", messages: [{ role: "user", content: "debug me" }] }),
});

```

Inspect stored call logs via SQLite:

```bash
sqlite3 ~/.omniroute/omniroute.db "SELECT id, request, response FROM call_logs WHERE request_id='123e4567-e89b-12d3-a456-426614174000';"

```

Enable tool-source diagnostics via UI settings:

```json
{
  "debugMode": true,
  "toolSourceDiagnostics": true
}

```

## Key Source Files for Debugging

When you need to step through code or verify wiring, consult these specific files in the `diegosouzapw/OmniRoute` repository:

- **[`src/app/api/v1/chat/completions/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/v1/chat/completions/route.ts)** – API entry point for request validation and routing to `open-sse`
- **[`open-sse/services/combo.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/services/combo.ts)** – Contains `resolveComboTargets()` for combo resolution and fallback logic
- **[`open-sse/translator/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/translator/index.ts)** – Format conversion pipelines for debugging translation mismatches
- **[`open-sse/executors/base.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/base.ts)** – Retry logic, header building, and proxy handling
- **[`src/lib/guardrails/pii-masker.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/pii-masker.ts)** – Redaction behavior controlled by `PII_REDACTION_ENABLED`
- **[`open-sse/mcp-server/server.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/mcp-server/server.ts)** – Tool registration, audit logging, and scope enforcement
- **`src/mitm/server.cjs`** – MITM proxy for TLS/HTTPS network-level inspection
- **[`src/lib/db/callLogs.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/callLogs.ts)** – Handles SQLite bound-param limits via chunked deletions
- **[`docs/reference/ENVIRONMENT.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/reference/ENVIRONMENT.md)** – Complete list of debug toggles
- **[`src/app/dashboard/settings/page.tsx`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/dashboard/settings/page.tsx)** – Implementation of the Debug Mode UI toggle

## Summary

- **OmniRoute debugging** operates across nine layers from API routes to file-system artifacts, each with specific entry points in `src/app/api/v1/`, `open-sse/`, and `src/lib/` directories.
- **Request IDs** are the primary correlation mechanism—grep these UUIDs across logs to trace the full pipeline from `contextManager` through [`combo.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/combo.ts) to the executors.
- **Environment variables** `APP_LOG_LEVEL=debug` and `OMNIROUTE_PROXY_FETCH_DEBUG=true` surface internal `pino` logs and proxy-relay diagnostics.
- **Dashboard tools** including the Translator Playground and Traffic Inspector provide visual debugging without code changes.
- **Common pitfalls** like SQLite variable limits and tool truncation have specific fixes in [`src/lib/db/callLogs.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/callLogs.ts) and [`chatcore/tools.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/chatcore/tools.ts) respectively.

## Frequently Asked Questions

### How do I find which component is causing an error in OmniRoute?

Start by locating the **request ID** in the initial log line, then grep for that ID across your logs to trace the execution flow. Check [`open-sse/contextManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/contextManager.ts) for context creation, [`open-sse/services/combo.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/services/combo.ts) for routing decisions, and `open-sse/executors/` for provider-specific errors. Enable `APP_LOG_LEVEL=debug` to see detailed `[Executor]` and `[Guardrail]` log lines that indicate exactly where the pipeline stops.

### What environment variables should I set to debug OmniRoute effectively?

Set **`APP_LOG_LEVEL=debug`** to enable all internal logging via `pino`, and **`OMNIROUTE_PROXY_FETCH_DEBUG=true`** to see `[ProxyFetch]` debug lines for proxy relay calls. For PII-related issues, check that `PII_REDACTION_ENABLED` and `PII_RESPONSE_SANITIZATION` are explicitly set to `false` unless you require data masking. These variables are documented in [`docs/reference/ENVIRONMENT.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/reference/ENVIRONMENT.md).

### How can I debug request translation issues between LLM providers?

Use the **Translator Playground** in the Dashboard. Navigate to **Dashboard → Translator**, paste your client-side OpenAI-style JSON payload, and click **Convert** to see the exact upstream request sent to providers like Anthropic or Gemini. The playground shows both the transformed request and the raw response, helping identify format mismatches in [`open-sse/translator/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/translator/index.ts).

### Where are tool invocation logs stored in OmniRoute?

Tool invocation logs and JSON-RPC flows are stored in the **`mcp_audit`** SQLite table by the MCP server in [`open-sse/mcp-server/server.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/mcp-server/server.ts). You can view these entries via the **Traffic Inspector** UI or query them directly using `sqlite3 ~/.omniroute/omniroute.db` with SQL statements filtering by `request_id`. Enable "Tool-source diagnostics" in the Dashboard settings to see which module originated each tool definition.