santifer/career-ops · error · Error
[models] Failed to fetch free model list: ${reason}. OPENROU
Error message
[models] Failed to fetch free model list: ${reason}. OPENROUTER_API_KEY is not set — copy .env.example to .env and add your key. What it means
Same wrapper as the models-fetch failure (openrouter-runner.mjs:140), but this branch is selected when process.env.OPENROUTER_API_KEY is falsy. The .env loader at the top of the script (lines 40-48) only reads .env from the script's own directory and only fills variables that are not already defined, and its regex requires a bare KEY=value line — so an empty var, a typo'd name, or spaces around '=' leaves the key unset. With no key the request still goes out (as 'Bearer undefined') and whatever failure resulted is appended as ${reason}.
Source
Thrown at openrouter-runner.mjs:140
if (list.length === 0) throw new Error('No free models found in API response');
// Sort by provider priority; within the same provider sort alphabetically
function providerOf(id) { return id.split('/')[0]; }
function priorityOf(id) {
const idx = PROVIDER_PRIORITY.indexOf(providerOf(id));
return idx === -1 ? PROVIDER_PRIORITY.length : idx;
}
freeModels = list.sort((a, b) => {
const diff = priorityOf(a) - priorityOf(b);
return diff !== 0 ? diff : a.localeCompare(b);
});
console.log(`[models] ${freeModels.length} free models loaded from OpenRouter API.`);
} catch (e) {
const reason = e instanceof Error ? e.message : String(e);
const hasKey = Boolean(process.env.OPENROUTER_API_KEY);
throw new Error(
`[models] Failed to fetch free model list: ${reason}. ` +
(hasKey ? 'Check that your API key is valid and that network access to OpenRouter is available.'
: 'OPENROUTER_API_KEY is not set — copy .env.example to .env and add your key.')
);
}
return freeModels;
}
// List and exit (helper command)
async function cmdModels() {
const models = await loadFreeModels();
console.log(`\nFree models available on OpenRouter (${models.length} total):\n`);
models.forEach((id, i) => console.log(` ${String(i + 1).padStart(2)}. ${id}`));
console.log('');
}
// ---------------------------------------------------------------------------View on GitHub (pinned to 60398d6549)
Solutions
- cp .env.example .env in the repo root, then set OPENROUTER_API_KEY=sk-or-v1-... (no spaces around '=', no quotes needed)
- Get a free key at https://openrouter.ai if you do not have one
- Alternatively export it in the shell: export OPENROUTER_API_KEY=sk-or-... (env vars win over .env)
- Verify with: node -e "console.log(Boolean(process.env.OPENROUTER_API_KEY))" from the same directory you run the runner from
Example fix
# before # .env contains: OPENROUTER_API_KEY = "sk-or-v1-xyz" (spaces break the parser) # after # .env contains: OPENROUTER_API_KEY=sk-or-v1-xyz
Defensive patterns
Strategy: validation
Validate before calling
// Gate before any run: the .env loader only fills UNDEFINED vars, so test exactly that
function assertOpenRouterKey() {
if (!process.env.OPENROUTER_API_KEY) {
throw new Error('OPENROUTER_API_KEY is not set. Copy .env.example to .env (repo root) and add your key — free at https://openrouter.ai');
}
} Try / catch
try {
await run(mode);
} catch (e) {
if (e.message.includes('OPENROUTER_API_KEY is not set')) {
console.error('Setup: cp .env.example .env && edit .env');
process.exit(3); // dedicated exit code for setup errors
}
throw e;
} Prevention
- Write .env lines as KEY=value with no spaces around '=' and no inline comments
- Verify with: node -e "console.assert(process.env.OPENROUTER_API_KEY, 'missing')" after editing .env
- Remember vars already present in the environment take precedence — an empty exported var suppresses the .env value
When it happens
Trigger: Running openrouter-runner.mjs with no .env in the repo root (or OPENROUTER_API_KEY= empty, or 'OPENROUTER_API_KEY = "sk-..."' with spaces that break the /^([A-Z_][A-Z0-9_]*)=(.*)$/ parse), causing the models fetch to fail; the catch then reports the missing key as the actionable cause.
Common situations: Fresh clone without copying .env.example to .env; key added to the wrong file (~/.env instead of repo .env); CI environment missing the secret; var name misspelled (OPENROUTER_KEY, OPENROUTER_APIKEY).
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- OPENROUTER_API_KEY not found. Copy .env.example to .env and
- [models] Failed to fetch free model list: ${reason}. Check t
- HTTP ${resp.status}: ${t.slice(0, 120)}
- Empty response
- Pinned model timed out after ${MODEL_TIMEOUT_MS / 1000}s
AI-assisted analysis of santifer/career-ops@60398d6549 (2026-08-20).
Data as JSON: /api/errors/915ea6dba9f5ce02.
Report an issue: GitHub.