santifer/career-ops · error · Error

[models] Failed to fetch free model list: ${reason}. Check t

Error message

[models] Failed to fetch free model list: ${reason}. Check that your API key is valid and that network access to OpenRouter is available.

What it means

Thrown by loadFreeModels() in openrouter-runner.mjs when fetching the OpenRouter /models endpoint to build the free-model list fails. The catch inspects the underlying error message and branches the hint: if OPENROUTER_API_KEY is set it suggests the key is invalid or network access is blocked; if the key is missing it points to copying .env.example. This is a startup precondition — without the model list, model rotation cannot proceed.

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 9b17a8ac97)

Solutions

  1. Confirm OPENROUTER_API_KEY is set and valid: `curl -H "Authorization: Bearer $OPENROUTER_API_KEY" https://openrouter.ai/api/v1/models`.
  2. Ensure .env is loaded (copy .env.example to .env, add key from https://openrouter.ai) and the runner sources it.
  3. Check network egress to openrouter.ai from the host/CI (no proxy block, DNS resolves).
  4. If OpenRouter is having an outage, retry shortly; if the free list is genuinely empty for your account, pin a model via CAREER_OPS_MODEL to bypass loadFreeModels.
Defensive patterns

Strategy: fallback

Validate before calling

// Smoke-test the OpenRouter models endpoint before launching a batch
const ok = await fetch('https://openrouter.ai/api/v1/models', {
  headers: { Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}` }
}).then(r => r.ok).catch(() => false);
if (!ok) { console.error('OpenRouter /models unreachable — fix key/network before batch'); process.exit(1); }

Try / catch

try {
  const models = await loadFreeModels();
} catch (e) {
  if (e.message.startsWith('[models] Failed to fetch free model list')) {
    // fall back to a pinned model so the run can proceed
    process.env.CAREER_OPS_MODEL = 'google/gemini-2.0-flash-exp:free';
  } else throw e;
}

Prevention

When it happens

Trigger: Any exception during the fetch/sort of the OpenRouter models list: HTTP 401/403 (bad key), network/DNS failure, OpenRouter API outage, rate limiting, or a malformed JSON response. The catch wraps the original reason into this message.

Common situations: OPENROUTER_API_KEY expired or revoked; corporate firewall/CI blocking openrouter.ai; .env not loaded; OpenRouter temporarily down; free-tier quota exhausted returning an error payload.

Related errors


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