{"record":{"id":"8721ca922d62df12","repo":"santifer/career-ops","slug":"all-active-length-active-models-failed-last-er","errorCode":null,"errorMessage":"All ${active.length} active models failed. Last error: ${lastError?.message}","messagePattern":"All (.+?) active models failed\\. Last error: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"openrouter-runner.mjs","lineNumber":345,"sourceCode":"        console.log(`SKIP (blacklisted: ${msg})`);\n      } else if (is429) {\n        rateLimitCounts[model] = (rateLimitCounts[model] ?? 0) + 1;\n        if (rateLimitCounts[model] >= 3) {\n          blacklistedModels.add(model);\n          saveBlacklist(blacklistedModels);\n          console.log(`SKIP (auto-blacklisted: persistent 429)`);\n        } else {\n          console.log(`FAILED (HTTP 429 [${rateLimitCounts[model]}/3])`);\n          await new Promise(r => setTimeout(r, 800));\n        }\n      } else {\n        console.log(`FAILED (${msg})`);\n        await new Promise(r => setTimeout(r, 800));\n      }\n    }\n  }\n\n  throw new Error(`All ${active.length} active models failed. Last error: ${lastError?.message}`);\n}\n\n// ---------------------------------------------------------------------------\n// Context loading\n// ---------------------------------------------------------------------------\nfunction loadContext() {\n  return {\n    cv:          readFile('cv.md')               ?? 'CV not found.',\n    profile:     readFile('config/profile.yml')  ?? '',\n    shared:      readFile('modes/_shared.md')    ?? '',\n    profileMode: readFile('modes/_profile.md')   ?? '',\n  };\n}\n\nexport function buildSystemPrompt(modeContent, ctx) {\n  const languageInstruction = outputLanguageInstruction(parseOutputLanguage(ctx.profile));\n  return [\n    ctx.shared,","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/openrouter-runner.mjs#L327-L363","documentation":"Thrown by callOpenRouter() after the rotation loop has tried every active (non-blacklisted) model and none succeeded. This is the terminal failure for the rotation path: lastError holds the most recent exception from the final attempt, and its message is appended so the caller knows the underlying cause (HTTP error, timeout, empty response, etc.).","triggerScenarios":"The for-loop over `active` models exhausted every model (attempt went 0..active.length-1) without a successful return — each iteration threw and was caught, updating lastError. Happens when a systemic issue (bad key, network outage, account/region problem, all models rate-limited) affects every model.","commonSituations":"OPENROUTER_API_KEY revoked/expired (401 on every model); network egress to openrouter.ai blocked from CI; sustained rate-limiting across all free models; OpenRouter-wide outage; account suspended or out of free-tier quota.","solutions":["Read lastError.message in the thrown text — it identifies the systemic cause (401/429/timeout) to fix first.","For 401: fix/regenerate OPENROUTER_API_KEY (error 68).","For 429s across all models: wait and reduce request rate; consider pinning one model and backing off.","For network errors: verify egress to openrouter.ai from the host/CI and retry.","For an OpenRouter outage: check status.openrouter.ai and retry later."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await callOpenRouter(systemPrompt, userMessage);\n} catch (e) {\n  if (e.message.startsWith('All ') && e.message.includes('active models failed')) {\n    // systemic failure — read the embedded lastError to decide: key, network, or outage\n    if (e.message.includes('HTTP 401')) {\n      throw new Error('OpenRouter key invalid — set OPENROUTER_API_KEY');\n    }\n    if (e.message.includes('HTTP 429')) {\n      // back off and retry after a delay\n      await new Promise(r => setTimeout(r, 5000));\n      return await callOpenRouter(systemPrompt, userMessage);\n    }\n  }\n  throw e;\n}","preventionTips":["Read the embedded lastError.message — it identifies the systemic cause (401/429/timeout).","Verify OPENROUTER_API_KEY and egress to openrouter.ai before batch runs.","Check status.openrouter.ai during suspected outages.","Rate-limit your requests to avoid carpet-bombing all free models into 429."],"tags":["api","openrouter","model-rotation","terminal-failure","network"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}