{"record":{"id":"a72a9a280b591522","repo":"santifer/career-ops","slug":"data-error-message","errorCode":null,"errorMessage":"${data.error.message}","messagePattern":"\\$\\{data\\.error\\.message\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"openrouter-runner.mjs","lineNumber":239,"sourceCode":"    const timerId = setTimeout(() => ctrl.abort(), MODEL_TIMEOUT_MS);\n    try {\n      const resp = await fetch(OPENROUTER_API_URL, {\n        method: 'POST',\n        headers: {\n          'Authorization': `Bearer ${key}`,\n          'Content-Type':  'application/json',\n          'HTTP-Referer':  'https://github.com/santifer/career-ops',\n          'X-Title':       'career-ops',\n        },\n        body,\n        signal: ctrl.signal,\n      });\n      if (!resp.ok) {\n        const t = await resp.text();\n        throw new Error(`HTTP ${resp.status}: ${t.slice(0, 120)}`);\n      }\n      const data = await resp.json();\n      if (data.error) throw new Error(data.error.message);\n      const content = data.choices?.[0]?.message?.content ?? '';\n      if (!content) throw new Error('Empty response');\n      console.log('OK');\n      const usage = normalizeOpenAIUsage(data.usage);\n      return { content, usage };\n    } catch (e) {\n      if (e.name === 'AbortError') throw new Error(`Pinned model timed out after ${MODEL_TIMEOUT_MS / 1000}s`);\n      throw e;\n    } finally {\n      clearTimeout(timerId);\n    }\n  }\n\n  const models = await loadFreeModels();\n  let lastError;\n\n  if (models.length === 0) {\n    throw new Error(","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/openrouter-runner.mjs#L221-L257","documentation":"Thrown in the pinned-model branch of callOpenRouter() when the OpenRouter response JSON contains a top-level error object (data.error) despite a 2xx status, or an error surfaced in the body. The message is verbatim data.error.message from OpenRouter — typically model-side content/policy errors, context-length issues, or provider routing failures.","triggerScenarios":"CAREER_OPS_MODEL is set, the HTTP call succeeded (resp.ok), resp.json() returned an object with a non-null `error` field. OpenRouter sometimes returns 200 with an error body when the upstream provider rejected the request (moderation, context overflow, provider outage).","commonSituations":"Input prompt exceeded the pinned model's context window; content tripped the provider's safety filter; upstream provider (Google/OpenAI/etc.) returned an error that OpenRouter forwarded; model temporarily unavailable on the provider side.","solutions":["Read data.error.message — it usually states the exact cause (context length, moderation, provider error).","Shorten the prompt / JD input if it's a context-length error; trim cv.md context or the JD payload.","Switch the pinned model (CAREER_OPS_MODEL) to one with a larger context window or different provider, or unset it to use rotation.","Retry once for transient provider errors; if it persists, the model may be down on OpenRouter's side."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await callOpenRouter(systemPrompt, userMessage);\n} catch (e) {\n  // provider-returned error body on the pinned path\n  if (process.env.CAREER_OPS_MODEL && e.message) {\n    // switch model or shorten prompt, then retry once\n    delete process.env.CAREER_OPS_MODEL;\n    return await callOpenRouter(shorten(systemPrompt), userMessage);\n  }\n  throw e;\n}","preventionTips":["Keep prompts within the pinned model's context window; trim cv.md context for long JDs.","Avoid content that trips provider safety filters.","Prefer rotation so one provider's error auto-skips to another.","Log data.choices[0].finish_reason to diagnose content-filter empty responses."],"tags":["api","openrouter","llm","pinned-model","content-policy"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}