decolua/9router · error

Missing API key

Error message

Missing API key

What it means

HTTP 401 returned by handleFetch when requireApiKey is enabled in gateway settings and no API key was supplied with the request. extractApiKey finds no key in headers (or query), so the handler rejects before validating anything else.

Source

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

  const targetUrl = body.url;
  const format = body.format;
  const maxCharacters = body.max_characters;

  log.request("POST", `${reqUrl.pathname} | ${providerInput}`);

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

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Add `Authorization: Bearer <gateway-api-key>` to the request
  2. Copy the exact key from dashboard settings into the client config/env
  3. If the gateway is local-only, disable requireApiKey in settings
  4. Check that your reverse proxy is not stripping the Authorization header

Example fix

// before
fetch('http://gw/v1/fetch', { method: 'POST', body })
// after
fetch('http://gw/v1/fetch', { method: 'POST', headers: { Authorization: `Bearer ${process.env.ROUTER_API_KEY}` }, body })
Defensive patterns

Strategy: type-guard

Validate before calling

const apiKey = process.env.ROUTER_API_KEY;
if (!apiKey) throw new Error('ROUTER_API_KEY is required when the gateway enforces requireApiKey');

Type guard

function isAuthedRequest(init) {
  const h = new Headers(init.headers);
  const auth = h.get('authorization') ?? '';
  return /^Bearer\s+\S+$/.test(auth);
}

Try / catch

const res = await post('/v1/fetch', body);
if (res.status === 401 && (await res.text()).includes('Missing API key')) {
  throw new Error('Gateway requires an API key — attach Authorization: Bearer <key>');
}

Prevention

When it happens

Trigger: POST to the fetch endpoint with no Authorization header (and no api key query param) while the router has requireApiKey=true.

Common situations: Key enforcement enabled after clients were built without auth; local scripts hitting a hardened remote gateway; test harnesses that skip auth headers; headers stripped by an intermediary proxy.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


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