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
- Verify the key against dashboard settings and update the client env var
- Trim whitespace around the key value in .env
- Ensure you are calling the intended gateway instance/environment
- 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
- Re-sync the key env var whenever dashboard settings change
- Trim env values; avoid copying with trailing newlines
- Label the gateway key distinctly from provider keys
- Rotate keys through a single config source
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/2e9607d7c228ca8d.
Report an issue: GitHub.