{"record":{"id":"340939e8c7b4cbf7","repo":"thedotmack/claude-mem","slug":"openrouter-api-error-data-error-code-data-error-message","errorCode":null,"errorMessage":"OpenRouter API error: ${data.error.code} - ${data.error.message}","messagePattern":"OpenRouter API error: (.+?) - (.+?)","errorType":"exception","errorClass":"ServerClassifiedProviderError","httpStatus":null,"severity":"error","filePath":"src/server/generation/providers/OpenRouterObservationProvider.ts","lineNumber":117,"sourceCode":"        headers: response.headers,\n        cause: new Error(`OpenRouter API error: ${response.status} - ${bodyText}`),\n        providerLabel: 'OpenRouter',\n      });\n    }\n\n    let data: OpenRouterResponse;\n    try {\n      data = (await response.json()) as OpenRouterResponse;\n    } catch (parseError) {\n      const err = parseError instanceof Error ? parseError : new Error(String(parseError));\n      throw new ServerClassifiedProviderError('OpenRouter returned invalid JSON', {\n        kind: 'parse_error',\n        cause: err,\n      });\n    }\n\n    if (data.error) {\n      throw classifyHttpProviderError({\n        status: response.status,\n        bodyText: `${data.error.code ?? ''} ${data.error.message ?? ''}`,\n        headers: response.headers,\n        cause: new Error(`OpenRouter API error: ${data.error.code} - ${data.error.message}`),\n        providerLabel: 'OpenRouter',\n      });\n    }\n\n    const rawText = data.choices?.[0]?.message?.content?.trim() ?? '';\n    if (!rawText) {\n      logger.warn('SDK', 'OpenRouter returned empty content', {\n        provider: 'openrouter',\n        model: this.model,\n      });\n    }\n\n    const tokensUsed = typeof data.usage?.total_tokens === 'number' ? data.usage.total_tokens : undefined;\n","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/server/generation/providers/OpenRouterObservationProvider.ts#L99-L135","documentation":"The OpenRouter response parsed as JSON but contains an `error` object (OpenRouter's OpenAI-style error envelope), so the provider throws classifyHttpProviderError with cause `OpenRouter API error: <code> - <message>` and bodyText built from data.error.code/message. This surfaces provider-side errors delivered with a parseable body — often model-not-found, moderation, or upstream provider failures.","triggerScenarios":"Parsed JSON has `data.error` present with fields like code ('model_not_found', 402, 429) and message — thrown at OpenRouterObservationProvider.ts:114-121.","commonSituations":"Requesting a model slug the account cannot access, upstream LLM provider outage relayed by OpenRouter with 200-ish status via gateway, moderation/refusal envelopes, credits errors delivered in-body.","solutions":["Read data.error.code/message in the cause: 'model_not_found' → use a valid slug; 402 → add credits; 429 → back off.","Verify the model slug and account access on openrouter.ai.","Retry with backoff only when the code indicates a transient/upstream failure.","Fall back to an alternate provider/model for resilient generation."],"exampleFix":"// before\nconst text = data.choices[0].message.content;\n// after\nif (data.error) throw new Error(`OpenRouter envelope: ${data.error.code} - ${data.error.message}`);\nconst text = data.choices?.[0]?.message?.content;","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function hasErrorEnvelope<T extends { error?: { code?: string | number; message?: string } }>(data: T): boolean {\n  return data.error != null;\n}","tryCatchPattern":"try {\n  result = await openRouterProvider.generate(prompt, signal);\n} catch (e) {\n  if (/model_not_found/.test(String(e.cause?.message))) return useFallbackModel();\n  if (e.kind === 'retryable') return retryWithBackoff();\n  throw e;\n}","preventionTips":["Check data.error before reading data.choices.","Validate model slugs and account access before shipping model IDs in config.","Route on data.error.code: 429/5xx → backoff; model_not_found/402 → fix config or credits.","Maintain a fallback model list for upstream provider failures."],"tags":["openrouter","api-error","json","error-envelope"],"backgroundTag":"upstream-api-error","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}