santifer/career-ops · error · Error

All loaded models have been blacklisted this session.

Error message

All loaded models have been blacklisted this session.

What it means

callOpenRouter rotates through a list of free OpenRouter models, blacklisting any model that fails during the session. This error is thrown when every model in the loaded list has been blacklisted, so no candidates remain for the request. It indicates the runner exhausted its model pool, not that the request itself was malformed.

Solutions

  1. Create a new runner instance / clear blacklistedModels so models get another chance (failures may be transient)
  2. Check OpenRouter status and your account's available free models; add more free model IDs to the loaded model list
  3. Inspect why models are failing (log the per-model error before blacklisting) and fix the root cause, e.g. rate limiting or an invalid key
  4. Reduce request rate / concurrency to stay under free-tier rate limits
  5. Fall back to a different provider or paid model if free capacity is exhausted

Example fix

// before
const active = models.filter(m => !blacklistedModels.has(m));
if (active.length === 0) throw new Error('All loaded models have been blacklisted this session.');
// after
let active = models.filter(m => !blacklistedModels.has(m));
if (active.length === 0 && models.length > 0) {
  console.warn('[model] all models blacklisted; resetting blacklist for retry');
  blacklistedModels.clear();
  active = models.slice();
}
Defensive patterns

Strategy: retry

Validate before calling

// before calling
const active = runner.getModels().filter(m => !runner.isBlacklisted(m));
if (active.length === 0) {
  runner.resetBlacklist(); // or recreate the runner
}

Try / catch

try {
  return await callOpenRouter(prompt);
} catch (e) {
  if (e.message.includes('blacklisted')) {
    runner.resetBlacklist();
    return await callOpenRouter(prompt); // one retry with fresh pool
  }
  throw e;
}

Prevention

When it happens

Trigger: Repeated calls to callOpenRouter in one session where each loaded model fails (timeouts, HTTP errors, empty responses) and is added to blacklistedModels; by the time a new request arrives, models.filter(m => !blacklistedModels.has(m)) returns an empty array.

Common situations: Long-running batch jobs that hammer free OpenRouter models until all hit rate limits or outages; an API key tier with very few free models that all fail quickly; a transient provider outage blacklisting the entire pool within one session.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16). Data as JSON: /api/errors/167fc431bed2c338. Report an issue: GitHub.

Appendix: source

Thrown at openrouter-runner.mjs:286

    } catch (e) {
      if (e.name === 'AbortError') throw new Error(`Pinned model timed out after ${MODEL_TIMEOUT_MS / 1000}s`);
      throw e;
    } finally {
      clearTimeout(timerId);
    }
  }

  const models = await loadFreeModels();
  let lastError;

  if (models.length === 0) {
    throw new Error(
      'No free OpenRouter models are available. Model loading may have failed, or your account currently has no free models.'
    );
  }
  // Build the active (non-blacklisted) model list in rotation order
  const active = models.filter(m => !blacklistedModels.has(m));
  if (active.length === 0) throw new Error('All loaded models have been blacklisted this session.');

  for (let attempt = 0; attempt < active.length; attempt++) {
    const model = active[(modelIndex % active.length + attempt) % active.length];
    activeModel = model;
    process.stdout.write(`[model] ${model} ... `);

    try {
      const body = JSON.stringify({
        model,
        messages: [
          buildCachedSystemMessage(systemPrompt),
          { role: 'user', content: userMessage },
        ],
        max_tokens: MAX_TOKENS,
      });

      const controller = new AbortController();
      const timerId = setTimeout(() => controller.abort(), MODEL_TIMEOUT_MS);

View on GitHub (pinned to aac998c7ed)