decolua/9router · error

Invalid API key

Error message

Invalid API key

What it means

HTTP 401 returned by handleFetch when requireApiKey is enabled and the supplied key fails isValidApiKey — i.e. the key exists but does not match the gateway's configured key.

Source

Thrown at src/sse/handlers/fetch.js:59

  // Log API key (masked)
  const apiKey = extractApiKey(request);
  if (apiKey) {
    log.debug("AUTH", `API Key: ${log.maskKey(apiKey)}`);
  } else {
    log.debug("AUTH", "No API key provided (local mode)");
  }

  // Enforce API key if enabled in settings
  const settings = await getSettings();
  if (settings.requireApiKey) {
    if (!apiKey) {
      log.warn("AUTH", "Missing API key (requireApiKey=true)");
      return errorResponse(HTTP_STATUS.UNAUTHORIZED, "Missing API key");
    }
    const valid = await isValidApiKey(apiKey);
    if (!valid) {
      log.warn("AUTH", "Invalid API key (requireApiKey=true)");
      return errorResponse(HTTP_STATUS.UNAUTHORIZED, "Invalid API key");
    }
  }

  if (!providerInput || typeof providerInput !== "string") {
    log.warn("FETCH", "Missing provider/model");
    return errorResponse(HTTP_STATUS.BAD_REQUEST, "Missing required field: provider (or model)");
  }

  if (!targetUrl || typeof targetUrl !== "string") {
    log.warn("FETCH", "Missing url");
    return errorResponse(HTTP_STATUS.BAD_REQUEST, "Missing required field: url");
  }

  // Validate URL format
  try {
    new URL(targetUrl);
  } catch {

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Verify the key against dashboard settings and update the client env var
  2. Trim whitespace around the key value in .env
  3. Ensure you are calling the intended gateway instance/environment
  4. Generate a fresh key in the dashboard and redeploy clients

Example fix

// before
Authorization: Bearer ${ROUTER_KEY.trim()} // value from stale env
// after
# .env updated with the current dashboard key, then restart
Authorization: Bearer ${ROUTER_API_KEY}
Defensive patterns

Strategy: validation

Validate before calling

const key = (process.env.ROUTER_API_KEY ?? '').trim();
if (!key || key.startsWith('sk-')) console.warn('Suspicious ROUTER_API_KEY: empty or looks like an upstream provider key');

Type guard

function looksLikeGatewayKey(k) {
  return typeof k === 'string' && k.trim().length >= 8;
}

Try / catch

const res = await post('/v1/fetch', body);
if (res.status === 401 && (await res.text()).includes('Invalid API key')) {
  console.error('Key rejected — re-sync ROUTER_API_KEY from dashboard settings and trim whitespace');
}

Prevention

When it happens

Trigger: POST to the fetch endpoint with an Authorization header whose bearer token is wrong, stale, or belongs to a different router instance while requireApiKey=true.

Common situations: Key rotated in the dashboard but client env var not updated; copying the upstream provider key instead of the gateway key; whitespace/newline in the env var; multiple gateway instances with different keys.

Understand the failure class

Related errors


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