diegosouzapw/OmniRoute · error · Error

OmniRoute

Error message

OmniRoute ${upstream.status}: ${errText}

What it means

MITM intercept for the Kiro client proxied the rewritten payload (model already mapped) to OmniRoute's own /v1/messages endpoint via fetchRouter and the router answered non-2xx; the router's status code and (possibly empty) error text are interpolated. The Kiro-facing side re-raises the router's failure — root cause is inside OmniRoute routing/auth, or the mapped model/target is unavailable; the catch in the handler turns it into an error response for the client.

Solutions

  1. Inspect the router's own logs for the same request to see which upstream/auth stage failed for /v1/messages
  2. Verify the mapped model is available and the Kiro connection credentials are valid in OmniRoute
  3. Check upstream.text() content when non-empty — it carries the router's sanitized error body
  4. If the failure is transient (upstream 5xx/timeout), let the client retry or enable fallback routing for that model
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at src/mitm/handlers/kiro.ts:36 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of diegosouzapw/OmniRoute@a179ffed5b (2026-08-25). Data as JSON: /api/errors/77417d95a3bc6f2d. Report an issue: GitHub.

Appendix: source

Thrown at src/mitm/handlers/kiro.ts:36

  async intercept(
    req: IncomingMessage,
    res: ServerResponse,
    body: Buffer,
    mappedModel: string,
  ): Promise<void> {
    const startedAt = this.now();
    const intercepted = await this.hookBufferStart(req, body, mappedModel);

    try {
      const payload = JSON.parse(body.toString());
      payload.model = mappedModel;

      const upstreamStart = this.now();
      const upstream = await this.fetchRouter(payload, "/v1/messages", req.headers);

      if (!upstream.ok) {
        const errText = await upstream.text().catch(() => "");
        throw new Error(`OmniRoute ${upstream.status}: ${errText}`);
      }

      let collected = "";
      await this.pipeSSE(upstream, res, (chunk) => {
        collected += chunk.toString();
      });

      const total = this.now() - startedAt;
      this.hookBufferUpdate(intercepted, {
        status: upstream.status,
        responseHeaders: Object.fromEntries(upstream.headers.entries()),
        responseBody: collected,
        responseSize: Buffer.byteLength(collected),
        proxyLatencyMs: upstreamStart - startedAt,
        upstreamLatencyMs: total - (upstreamStart - startedAt),
      });
    } catch (err) {
      await this.hookBufferError(intercepted, err);

View on GitHub (pinned to a179ffed5b)