# How to Debug OmniRoute: A Layer-by-Layer Debugging Guide

> Debug OmniRoute effectively with our layer-by-layer guide. Learn to trace requests using UUIDs via the Traffic Inspector or command-line logs. Enable debug logs for deeper insights.

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

---

**Enable `APP_LOG_LEVEL=debug` and `OMNIROUTE_PROXY_FETCH_DEBUG=true`, then trace requests by their UUID through the Dashboard's Traffic Inspector or command-line logs.**

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, layered approach. This guide shows you how to debug an OmniRoute application using environment flags, UI toggles, and targeted source code inspection.

---

## Debug Layers: What to Check and Where

OmniRoute's architecture spans nine distinct layers. Identify which layer your issue belongs to, then use the corresponding entry point and debug toggle.

| Layer | What to examine | Entry point | Debug toggle |
|-------|-----------------|-------------|--------------|
| **Request-level logs** | Request ID, timestamps, provider & model chosen, auth header sanitization | `src/app/api/v1/**/route.ts` (e.g., [`chat/completions/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/chat/completions/route.ts)) | `APP_LOG_LEVEL=debug` or UI "Debug Mode" toggle |
| **Context manager** | Per-request context with metadata (request ID, provider, combo, rate-limit info) | [`open-sse/contextManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/contextManager.ts) | Automatic with `APP_LOG_LEVEL=debug` |
| **Combo routing** | Target resolution, strategy selection, fallback decisions | [`open-sse/services/combo.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/services/combo.ts) → `resolveComboTargets()` | `debugMode` or Dashboard "Traffic Inspector" |
| **Translator / Transformer** | Request format conversion (OpenAI ↔ Anthropic, Gemini, etc.) and response back-translation | `open-sse/translator/` and `open-sse/transformer/` | Dashboard → Translator playground |
| **Executor** | Provider-specific request building, headers, retries, proxy routing | `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)) | `OMNIROUTE_PROXY_FETCH_DEBUG=true` |
| **Guardrails** | Prompt-injection guard, PII redaction, tool-source diagnostics | `src/lib/guardrails/` | "Tool-source diagnostics" toggle in Dashboard → Settings → Debug |
| **MCP / A2A** | Tool invocation logs, scope checks, JSON-RPC flow | `open-sse/mcp-server/` and `src/lib/a2a/` | SQLite `mcp_audit` table via Traffic Inspector UI |
| **Database / Persistence** | Call-log trimming, quota snapshots, compression stats | `src/lib/db/` modules | Automatic; check for "too many SQL variables" errors |
| **File-system artifacts** | Legacy log files (`${DATA_DIR}/log.txt`, `call_logs/`) | [`src/lib/db/healthCheck.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/healthCheck.ts) | Available when `APP_LOG_LEVEL=debug` |

---

## Step-by-Step Debugging Workflow

### 1. Reproduce the Issue Locally

Start the development server with full debug output enabled:

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

```

### 2. Capture the Request ID

Every request logs a UUID on its first line. Example:

```

[2024-01-15T10:23:45.123Z] req=123e4567-e89b-12d3-a456-426614174000 model=gpt-4o provider=openai

```

Copy this `req=` value—it's your tracing key through the entire pipeline.

### 3. Trace the Request Through the Pipeline

Grep the request ID to follow its path:

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

```

Expected log sequence:

- **Context creation** ([`contextManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/contextManager.ts)) — initializes request metadata
- **Combo resolution** ([`combo.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/combo.ts)) — determines target providers and fallback order
- **Translator input/output** ([`translator/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/translator/index.ts)) — shows format conversion
- **Executor call** (`executors/*`) — provider-specific request execution
- **Final SSE stream or JSON response**

### 4. Enable Fine-Grained Debug Modes

Beyond `APP_LOG_LEVEL=debug`, activate these for specific issues:

- **UI Debug Mode**: Settings → Advanced → Debug Mode toggle reveals hidden sidebar panels (Translator, Playground, Search Tools)
- **Tool-source diagnostics**: Dashboard → Settings → Debug → enable to label each tool with its originating module
- **Proxy fetch debug**: `OMNIROUTE_PROXY_FETCH_DEBUG=true` emits `[ProxyFetch]` lines for every proxy-relay call

### 5. Use Dashboard Inspection Tools

| Tool | Location | Purpose |
|------|----------|---------|
| **Translator Playground** | Dashboard → Translator | Paste OpenAI-style JSON, see exact upstream request, edit, and re-run |
| **Traffic Inspector** | Dashboard sidebar | Visualizes tool calls, combo targets, and proxy hops |
| **Live Monitor** | Dashboard | Streams raw SSE chunks from live requests in real time |

### 6. Check Guardrail Activity

Guardrail modules write concise `[Guardrail]` log lines when modifying or blocking payloads. Look for:

```

[Guardrail] PII_REDACTION_ENABLED=true, redacted 3 entities
[Guardrail] prompt-injection score=0.87, blocked

```

### 7. Verify Database Limits

If you encounter SQLite-related errors, run the relevant test to confirm bound-parameter limits are handled correctly:

```bash
npm run typecheck:core && node --import tsx/esm --test tests/unit/call-log-trim-sql-vars-5217.test.ts

```

The `deleteCallLogRowsByIds` function in [`src/lib/db/callLogs.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/callLogs.ts) now automatically chunks deletions to ≤500 per statement to avoid "too many SQL variables" errors.

---

## Common Debugging Pitfalls and Fixes

| Symptom | Root cause | Fix |
|---------|-----------|-----|
| Empty response body | Provider returned no data, but executor suppressed the error | Set `APP_LOG_LEVEL=debug`; search for "`[Executor] response empty`" |
| Tool list truncated | Legacy `MAX_TOOLS_LIMIT=128` applied | Update to latest version—Opencode clients now receive full lists unless provider-specific limits apply (see [`chatcore/tools.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/chatcore/tools.ts)) |
| `[ProxyEgress]` shows `proxy=direct` incorrectly | Proxy context not threaded through AsyncLocalStorage | Verify proxy pool configuration and enable `APP_LOG_LEVEL=debug` to see actual proxy name |
| SQLite "Too many SQL variables" | `deleteCallLogRowsByIds` attempted single `IN (...)` with >999 IDs | Now batched automatically in [`src/lib/db/callLogs.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/callLogs.ts) |
| Unexpected PII redaction | `PII_REDACTION_ENABLED` or `PII_RESPONSE_SANITIZATION=true` | Unset these env vars unless intentional masking required |
| MCP tool-routing confusion | Tool-source diagnostics disabled | Enable toggle; inspector will label each tool with origin module |

---

## Code Examples for OmniRoute Debugging

### Programmatic Request Tracing

Pass a custom request ID to correlate client and server logs:

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

const requestId = uuidv4(); // trace this through the pipeline

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" }] 
  }),
});

```

### Query Stored Call Logs (SQLite)

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

```

### Enable Debug via UI Configuration

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

```

Set in Dashboard → Settings → Advanced, or pass as initialization config.

---

## Key Source Files for Debugging

These files are your primary entry points when stepping through request flow or verifying wiring:

| Component | File | What to inspect |
|-----------|------|---------------|
| API entry | [[`src/app/api/v1/chat/completions/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/v1/chat/completions/route.ts)](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.49/src/app/api/v1/chat/completions/route.ts) | Request validation, auth extraction, routing to `open-sse` |
| Combo routing | [[`open-sse/services/combo.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/services/combo.ts)](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.49/open-sse/services/combo.ts) | `resolveComboTargets()` for target resolution and fallback logic |
| Translator | [[`open-sse/translator/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/translator/index.ts)](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.49/open-sse/translator/index.ts) | Format conversion pipelines |
| Executor base | [[`open-sse/executors/base.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/executors/base.ts)](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.49/open-sse/executors/base.ts) | Retry logic, header building, proxy handling |
| Guardrails | [[`src/lib/guardrails/pii-masker.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/pii-masker.ts)](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.49/src/lib/guardrails/pii-masker.ts) | Redaction behavior; check `PII_REDACTION_ENABLED` |
| MCP server | [[`open-sse/mcp-server/server.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/mcp-server/server.ts)](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.49/open-sse/mcp-server/server.ts) | Tool registration, audit logging, scope enforcement |
| MITM proxy | [`src/mitm/server.cjs`](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.49/src/mitm/server.cjs) | TLS/HTTPS network-level inspection |
| Environment reference | [[`docs/reference/ENVIRONMENT.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/reference/ENVIRONMENT.md)](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.49/docs/reference/ENVIRONMENT.md) | Complete list of debug toggles |
| Dashboard settings | [[`src/app/dashboard/settings/page.tsx`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/dashboard/settings/page.tsx)](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.49/src/app/dashboard/settings/page.tsx) | How Debug Mode propagates server-side |
| Call-log handling | [[`src/lib/db/callLogs.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/callLogs.ts)](https://github.com/diegosouzapw/OmniRoute/blob/release/v3.8.49/src/lib/db/callLogs.ts) | Chunked deletion logic for SQLITE limits |

---

## Summary

- **Start with environment flags**: `APP_LOG_LEVEL=debug` and `OMNIROUTE_PROXY_FETCH_DEBUG=true` surface the most detail with minimal configuration
- **Capture and grep the request ID**: Every log line includes `req=UUID` for end-to-end tracing
- **Use the Dashboard tools**: Translator Playground, Traffic Inspector, and Live Monitor provide visual, interactive debugging
- **Layer your investigation**: Work from request logs → context → combo routing → translator → executor → guardrails → database
- **Reference source files directly**: The paths above link to the exact implementation in the OmniRoute repository

---

## Frequently Asked Questions

### How do I enable debug mode in OmniRoute?

Set `APP_LOG_LEVEL=debug` in your environment and start the server with `npm run dev`. Alternatively, enable the "Debug Mode" toggle in the Dashboard under Settings → Advanced. For proxy-specific issues, also set `OMNIROUTE_PROXY_FETCH_DEBUG=true`.

### Where does OmniRoute store request logs?

Request logs appear in stdout when `APP_LOG_LEVEL=debug` is set. Persistent logs are stored in SQLite at `~/.omniroute/omniroute.db` with the `call_logs` table. Legacy file-based logs exist in `${DATA_DIR}/log.txt` and `call_logs/` for backward compatibility.

### How can I see which tool definition a tool originated from?

Enable "Tool-source diagnostics" in Dashboard → Settings → Debug. This toggle causes the Traffic Inspector to label each tool with its originating module. The MCP server also writes audit rows to the `mcp_audit` table for per-tool invocation history.

### Why am I getting empty responses from OmniRoute?

Empty responses typically occur when a provider returns no data but the executor suppresses the error. Set `APP_LOG_LEVEL=debug` and search logs for "`[Executor] response empty`" to identify the failing provider call. Also verify that `PII_REDACTION_ENABLED` is not excessively redacting valid content.