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

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) 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 Automatic with APP_LOG_LEVEL=debug
Combo routing Target resolution, strategy selection, fallback decisions open-sse/services/combo.tsresolveComboTargets() 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, 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 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:

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:

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

Expected log sequence:

  • Context creation (contextManager.ts) — initializes request metadata
  • Combo resolution (combo.ts) — determines target providers and fallback order
  • Translator input/output (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:

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 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)
[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
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:

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)

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

Enable Debug via UI Configuration

{
  "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/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/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/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/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/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/release/v3.8.49/open-sse/mcp-server/server.ts) Tool registration, audit logging, scope enforcement
MITM proxy src/mitm/server.cjs TLS/HTTPS network-level inspection
Environment reference [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/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/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.

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 →