santifer/career-ops · critical · Error

OPENROUTER_API_KEY not found. Copy .env.example to .env and

Error message

OPENROUTER_API_KEY not found.
Copy .env.example to .env and add your API key.
Free key: https://openrouter.ai

What it means

Thrown by callOpenRouter() in openrouter-runner.mjs when process.env.OPENROUTER_API_KEY is falsy at call time. This is the hard precondition before any HTTP request — there is no fallback, no anonymous access. The message directs the user to copy .env.example to .env and obtain a free key from openrouter.ai.

Source

Thrown at openrouter-runner.mjs:201

// Providers that support caching (Anthropic, Gemini, …) reuse the prefix across
// back-to-back calls within the cache TTL; providers that don't simply ignore
// the field, so this is a safe passthrough that never changes the prompt text.
export function buildCachedSystemMessage(systemPrompt) {
  return {
    role: 'system',
    content: [
      { type: 'text', text: systemPrompt, cache_control: { type: 'ephemeral' } },
    ],
  };
}

// ---------------------------------------------------------------------------
// OpenRouter API call — automatic model rotation with fallback
// ---------------------------------------------------------------------------
async function callOpenRouter(systemPrompt, userMessage) {
  const key = process.env.OPENROUTER_API_KEY;
  if (!key) {
    throw new Error(
      'OPENROUTER_API_KEY not found.\n' +
      'Copy .env.example to .env and add your API key.\n' +
      'Free key: https://openrouter.ai'
    );
  }

  const pinnedModel = process.env.CAREER_OPS_MODEL;
  if (pinnedModel) {
    activeModel = pinnedModel;
    process.stdout.write(`[model] ${pinnedModel} (pinned) ... `);
    const body = JSON.stringify({
      model: pinnedModel,
      messages: [
        buildCachedSystemMessage(systemPrompt),
        { role: 'user', content: userMessage },
      ],
      max_tokens: MAX_TOKENS,
    });

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Copy .env.example to .env and add your key: OPENROUTER_API_KEY=sk-or-v1-...
  2. Get a free key at https://openrouter.ai if you don't have one.
  3. Verify it's visible: `node -e "console.log(Boolean(process.env.OPENROUTER_API_KEY))"` after loading .env, or export it directly in the shell.
  4. In CI, set the OPENROUTER_API_KEY secret on the job.

Example fix

# before: .env missing or empty

# after: .env
OPENROUTER_API_KEY=sk-or-v1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Defensive patterns

Strategy: validation

Validate before calling

if (!process.env.OPENROUTER_API_KEY) {
  throw new Error('Missing OPENROUTER_API_KEY. Copy .env.example to .env and add your key from https://openrouter.ai');
}

Prevention

When it happens

Trigger: Running the runner without OPENROUTER_API_KEY in the environment: .env missing, .env not loaded by the runner, key line commented out, or running in a shell/CI that didn't export it.

Common situations: Fresh clone without .env; CI secret not configured; renamed key; running via a wrapper that strips env; key set in a different shell than the one invoking the runner.

Related errors


AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13). Data as JSON: /api/errors/d7c185f43e49fa73. Report an issue: GitHub.