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
- Add `Authorization: Bearer <gateway-api-key>` to the request
- Copy the exact key from dashboard settings into the client config/env
- If the gateway is local-only, disable requireApiKey in settings
- 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
- Attach the auth header via a shared request wrapper so it is never forgotten
- Keep a health-check script that verifies auth before batch runs
- Note in team docs whether each environment enforces requireApiKey
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.