decolua/9router · error
Missing API key
Error message
Missing API key
What it means
Auth guard in handleSearch (src/sse/handlers/search.js:51): when the server setting requireApiKey is enabled and extractApiKey(request) finds no API key on the request, the handler returns HTTP 401 'Missing API key'. 9Router exposes an OpenAI-compatible gateway; once API-key enforcement is switched on in dashboard settings, every programmatic call must carry the key even from localhost.
Source
Thrown at src/sse/handlers/search.js:51
// Accept either `provider` or `model` (UI sends `model` since provider IS the model for webSearch)
const providerInput = body.provider || body.model;
const query = body.query;
log.request("POST", `${url.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("SEARCH", "Missing provider/model");
return errorResponse(HTTP_STATUS.BAD_REQUEST, "Missing required field: provider (or model)");
}
if (!query || typeof query !== "string" || !query.trim()) {
log.warn("SEARCH", "Missing query");
return errorResponse(HTTP_STATUS.BAD_REQUEST, "Missing required field: query");
}View on GitHub (pinned to 90b52e06ff)
Solutions
- Attach the key as Authorization: Bearer <your-9router-api-key> on the request.
- Alternatively send it in the x-api-key header (whichever extractApiKey supports).
- Verify the key matches one generated in the dashboard (API keys section) and that requireApiKey is intentionally on.
- If this is a trusted local-only setup, disable requireApiKey in dashboard settings.
- Check the reverse proxy/middleware config isn't stripping Authorization before it reaches 9Router.
Example fix
// before
await fetch(base + '/v1/search', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) });
// after
await fetch(base + '/v1/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.ROUTER_API_KEY}` },
body: JSON.stringify(payload)
}); Defensive patterns
Strategy: validation
Validate before calling
const key = process.env.ROUTER_API_KEY;
if (!key) throw new Error('ROUTER_API_KEY is required: the gateway has requireApiKey enabled');
// optional pre-check
const probe = await fetch(base + '/v1/models', { headers: { Authorization: `Bearer ${key}` } });
if (probe.status === 401) throw new Error('Gateway rejects the configured API key'); Try / catch
const res = await doSearch();
if (res.status === 401) {
const msg = await res.text();
if (msg.includes('Missing API key')) throw new Error('Attach Authorization: Bearer <key> — requireApiKey is enabled');
throw new Error('Auth failed: ' + msg);
} Prevention
- Load the key from env/config in every client that talks to the gateway; never hardcode or omit it.
- Keep requireApiKey state documented for your deployment so local scripts are updated when it flips on.
- Verify reverse proxies preserve the Authorization header.
- Send the key in the header format extractApiKey recognizes (Authorization: Bearer or x-api-key).
When it happens
Trigger: POST to the /v1 search endpoint while settings.requireApiKey === true and the request carries no API key: no Authorization: Bearer header, no x-api-key header, and no other header extractApiKey recognizes.
Common situations: Local dev scripts that worked before API-key enforcement was enabled in the dashboard; a team member toggled requireApiKey on; a reverse proxy strips the Authorization header; the client sends the key under a custom header name the gateway's extractApiKey does not read; environment changed from no-auth local mode to a shared deployment.
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/93770f2a6121d40b.
Report an issue: GitHub.