{"record":{"id":"9d94f4302953b7d1","repo":"can1357/oh-my-pi","slug":"response-status-response-statustext","errorCode":null,"errorMessage":"${response.status} ${response.statusText}","messagePattern":"\\$\\{response\\.status\\} \\$\\{response\\.statusText\\}","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/mnemopi/src/core/extraction/client.ts","lineNumber":124,"sourceCode":"\t\tdiag.recordFailure(\"cloud\", lastError, \"all_models_failed\");\n\t\treturn \"\";\n\t}\n\n\tasync callApi(\n\t\tmodel: string,\n\t\tmessages: readonly ChatMessage[],\n\t\ttemperature: number,\n\t\tmaxTokens: number,\n\t\tapiKey = \"\",\n\t): Promise<string> {\n\t\tconst response = await this.fetchImpl(`${this.baseUrl}/chat/completions`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: authHeader(apiKey),\n\t\t\tbody: JSON.stringify({ model, messages, temperature, max_tokens: maxTokens }),\n\t\t\tsignal: AbortSignal.timeout(60000),\n\t\t});\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`${response.status} ${response.statusText}`.trim());\n\t\t}\n\t\tconst data = (await response.json()) as {\n\t\t\tchoices?: Array<{ message?: { content?: unknown } }>;\n\t\t};\n\t\tthis.callCount += 1;\n\t\tconst content = data.choices?.[0]?.message?.content;\n\t\treturn typeof content === \"string\" ? content : \"\";\n\t}\n\n\tasync extractFacts(messages: readonly ChatMessage[]): Promise<ExtractedFact[]> {\n\t\tlet conversationText = \"\";\n\t\tfor (let i = 0; i < messages.length; i += 1) {\n\t\t\tconst msg = messages[i];\n\t\t\tif (msg === undefined) continue;\n\t\t\tconst content = msg.content.trim();\n\t\t\tif (content !== \"\") {\n\t\t\t\tconversationText += `[${i}] [${msg.role || \"unknown\"}]: ${content}\\n`;\n\t\t\t}","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/mnemopi/src/core/extraction/client.ts#L106-L142","documentation":"callApi in the extraction client throws a plain Error containing `<status> <statusText>` whenever the chat-completions POST returns a non-OK response. It is a thin surface of the provider's HTTP error; the body (which usually holds a JSON error detail) is not included.","triggerScenarios":"Any non-2xx from the extraction LLM API: invalid model name (404), bad/missing API key (401), rate limits (429), server errors (5xx), or an unreachable gateway returning 502.","commonSituations":"Misconfigured `model` string after a provider renamed a model, exhausted quota, network proxies, or transient upstream outages during batch extraction.","solutions":["Read the status in the message: 401 → fix the API key; 404 → fix the model name; 429 → back off / reduce concurrency.","Log or inspect the raw provider response body for the detailed error (capture with a wrapper fetch if needed).","Retry with exponential backoff for 429/5xx; do not retry 4xx client errors.","Verify base URL and network/proxy reachability for 5xx/502 statuses."],"exampleFix":"// before\nawait extractor.result(prompt); // throws \"429 Too Many Requests\"\n// after\ntry {\n  await extractor.result(prompt);\n} catch (e) {\n  if (String(e.message).startsWith(\"429\")) await Bun.sleep(5000); // then retry\n  else throw e;\n}","handlingStrategy":"retry","validationCode":"const res = await fetch(url, { method: \"HEAD\", headers: authHeader(apiKey) });\nif (!res.ok) throw new Error(`Extraction API preflight failed: ${res.status}`);","typeGuard":null,"tryCatchPattern":"try {\n  return await client.result(messages);\n} catch (e) {\n  const m = /^([45]\\d\\d)/.exec(String(e.message));\n  if (m && (m[1] === \"429\" || m[1].startsWith(\"5\"))) {\n    await Bun.sleep(2000); // then retry with backoff\n  }\n  throw e;\n}","preventionTips":["Pin the model name in config and verify it against the provider's current roster.","Add client-side rate limiting to stay under provider 429 thresholds.","Wrap the client with a retry helper (exponential backoff, retry only 429/5xx)."],"tags":["http","network","llm-api","status-code"],"backgroundTag":"http-error-status","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}