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
- Create a new runner instance / clear blacklistedModels so models get another chance (failures may be transient)
- Check OpenRouter status and your account's available free models; add more free model IDs to the loaded model list
- 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
- Reduce request rate / concurrency to stay under free-tier rate limits
- 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
- Log each model's failure reason when blacklisting so root causes surface
- Cap blacklist growth per session and reset it periodically
- Keep the free-model list current with OpenRouter's catalog
- Throttle request rate to stay under free-tier limits
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)