{"record":{"id":"1f102006b1983618","repo":"santifer/career-ops","slug":"models-failed-to-fetch-free-model-list-reason-haskey-check","errorCode":null,"errorMessage":"[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.')}","messagePattern":"\\[models\\] Failed to fetch free model list: (.+?)\\. (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"openrouter-runner.mjs","lineNumber":152,"sourceCode":"    if (list.length === 0) throw new Error('No free models found in API response');\n\n    // Sort by provider priority; within the same provider sort alphabetically\n    function providerOf(id) { return id.split('/')[0]; }\n    function priorityOf(id) {\n      const idx = PROVIDER_PRIORITY.indexOf(providerOf(id));\n      return idx === -1 ? PROVIDER_PRIORITY.length : idx;\n    }\n\n    freeModels = list.sort((a, b) => {\n      const diff = priorityOf(a) - priorityOf(b);\n      return diff !== 0 ? diff : a.localeCompare(b);\n    });\n\n    console.log(`[models] ${freeModels.length} free models loaded from OpenRouter API.`);\n  } catch (e) {\n    const reason = e instanceof Error ? e.message : String(e);\n    const hasKey = Boolean(process.env.OPENROUTER_API_KEY);\n    throw new Error(\n      `[models] Failed to fetch free model list: ${reason}. ` +\n      (hasKey ? 'Check that your API key is valid and that network access to OpenRouter is available.'\n               : 'OPENROUTER_API_KEY is not set — copy .env.example to .env and add your key.')\n    );\n  }\n\n  return freeModels;\n}\n\n// List and exit (helper command)\nasync function cmdModels() {\n  const models = await loadFreeModels();\n  console.log(`\\nFree models available on OpenRouter (${models.length} total):\\n`);\n  models.forEach((id, i) => console.log(`  ${String(i + 1).padStart(2)}. ${id}`));\n  console.log('');\n}\n\n// ---------------------------------------------------------------------------","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/openrouter-runner.mjs#L134-L170","documentation":"Wrapping error thrown by loadFreeModels()'s catch block: any failure inside the fetch/parse/filter sequence (including errors 91/92) is rethrown with the `[models]` prefix, the original reason, and context-dependent advice — a key-validation hint if OPENROUTER_API_KEY is set, or a setup hint if it is missing. This is the error a caller actually sees; the original cause is embedded in the message.","triggerScenarios":"Any of: HTTP error from the models endpoint (see err 91), JSON parse failure of the response, `data.data` missing/undefined, or an empty free-model list — all caught and re-wrapped by line 152.","commonSituations":"No .env file (key undefined → second message branch); invalid key (401 → first branch); DNS/network failure; OpenRouter outage; API payload drift.","solutions":["Read the embedded `reason` after the colon — it is the real cause (HTTP status, JSON error, etc.).","If the message says OPENROUTER_API_KEY is not set: `cp .env.example .env` and add a key from https://openrouter.ai/keys.","If a key is set: verify it is valid and that the machine can reach openrouter.ai (curl the models endpoint).","Ensure your dotenv loading actually runs before this module — a key set only in .env but not loaded still counts as unset.","On transient network errors, retry; on persistent 5xx, check OpenRouter status."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (!process.env.OPENROUTER_API_KEY) {\n  throw new Error('Setup required: cp .env.example .env and add OPENROUTER_API_KEY from https://openrouter.ai');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await runEvaluation();\n} catch (err) {\n  if (String(err.message).startsWith('[models]')) {\n    console.error('OpenRouter model list problem:', err.message);\n    console.error('Fix the root cause shown after the colon, then retry.');\n  } else throw err;\n}","preventionTips":["Load .env (dotenv) before importing any runner module.","Pre-flight check the key with a cheap authenticated request at startup.","Keep the wrapped reason visible in logs — it names the real failure.","Distinguish the no-key vs bad-key branches when writing runbooks."],"tags":["openrouter","api-key","network","error-wrapping"],"backgroundTag":"api-request-failed","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}