decolua/9router · error

[copilot] ${error.message}

Error message

[copilot] ${error.message}

What it means

The copilot MITM handler remaps the model, resolves the router path from the incoming URL, forwards to the local router and pipes SSE back. Any exception is logged '[copilot] <message>' and returned to the client as a 500 JSON body with type 'mitm_error'.

Source

Thrown at src/mitm/handlers/copilot.js:29

function resolveRouterPath(reqUrl) {
  for (const [pattern, routerPath] of Object.entries(URL_MAP)) {
    if (reqUrl.includes(pattern)) return routerPath;
  }
  return "/v1/chat/completions";
}

/**
 * Intercept Copilot request — replace model and forward to matching 9Router endpoint
 */
async function intercept(req, res, bodyBuffer, mappedModel) {
  try {
    const body = JSON.parse(bodyBuffer.toString());
    body.model = mappedModel;
    const routerPath = resolveRouterPath(req.url);
    const routerRes = await fetchRouter(body, routerPath, req.headers);
    await pipeSSE(routerRes, res);
  } catch (error) {
    err(`[copilot] ${error.message}`);
    if (!res.headersSent) res.writeHead(500, { "Content-Type": "application/json" });
    res.end(JSON.stringify({ error: { message: error.message, type: "mitm_error" } }));
  }
}

module.exports = { intercept };

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Start the 9Router gateway and confirm the MITM target port matches it.
  2. Inspect the mitm_error message: ECONNREFUSED → gateway down; JSON errors → body format issue.
  3. Verify the copilot tool's request URL maps to a supported router path.
  4. Re-check the copilot connection credentials in the dashboard if the router returns 401.

Example fix

// before
curl -x http://127.0.0.1:MITM_PORT https://api.githubcopilot.com/...  # gateway down → mitm_error
// after
PORT=20128 npm run start && curl -x http://127.0.0.1:MITM_PORT https://api.githubcopilot.com/...
Defensive patterns

Strategy: try-catch

Validate before calling

const health = await fetch('http://127.0.0.1:20128/dashboard').then(r => r.ok).catch(() => false);
if (!health) throw new Error('Router gateway not reachable');
const body = JSON.parse(bodyBuffer.toString());
if (!body.model) throw new Error('Request body missing model field');

Try / catch

try {
  const routerRes = await fetchRouter(body, resolveRouterPath(req.url), req.headers);
  await pipeSSE(routerRes, res);
} catch (error) {
  err(`[copilot] ${error.message}`);
  if (!res.headersSent) res.writeHead(500, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ error: { message: error.message, type: 'mitm_error' } }));
}

Prevention

When it happens

Trigger: intercept() fails on JSON.parse of the request body, resolveRouterPath on an unexpected URL, fetchRouter connection refused (gateway down), or pipeSSE stream failure.

Common situations: GitHub Copilot CLI/extension pointed at the MITM port while the 9Router server is stopped; copilot sends an endpoint path the router doesn't expose; unauthenticated or malformed copilot request bodies.

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/dab3c39e69a4837f. Report an issue: GitHub.