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

  1. cp .env.example .env in the repo root, then set OPENROUTER_API_KEY=sk-or-v1-... (no spaces around '=', no quotes needed)
  2. Get a free key at https://openrouter.ai if you do not have one
  3. Alternatively export it in the shell: export OPENROUTER_API_KEY=sk-or-... (env vars win over .env)
  4. 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

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


AI-assisted analysis of santifer/career-ops@60398d6549 (2026-08-20). Data as JSON: /api/errors/915ea6dba9f5ce02. Report an issue: GitHub.