{"record":{"id":"6b03e5a976843fc1","repo":"midudev/autoskills","slug":"openai-res-status-text-slice-0-200","errorCode":null,"errorMessage":"OpenAI ${res.status}: ${text.slice(0, 200)}","messagePattern":"OpenAI (.+?): (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/autoskills/scripts/sync-skills.mjs","lineNumber":522,"sourceCode":"  const res = await fetch(\"https://api.openai.com/v1/chat/completions\", {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application/json\",\n      Authorization: `Bearer ${apiKey}`,\n    },\n    body: JSON.stringify({\n      model: REVIEW_MODEL,\n      response_format: { type: \"json_object\" },\n      messages: [\n        { role: \"system\", content: REVIEW_SYSTEM_PROMPT },\n        { role: \"user\", content: userMsg },\n      ],\n    }),\n  });\n\n  if (!res.ok) {\n    const text = await res.text().catch(() => \"\");\n    throw new Error(`OpenAI ${res.status}: ${text.slice(0, 200)}`);\n  }\n  const payload = await res.json();\n  const raw = payload.choices?.[0]?.message?.content ?? \"{}\";\n  let parsed;\n  try {\n    parsed = JSON.parse(raw);\n  } catch {\n    return {\n      status: \"rejected\",\n      flags: [\"invalid-json\"],\n      summary: \"auditor returned invalid JSON\",\n    };\n  }\n  const status = [\"approved\", \"flagged\", \"rejected\"].includes(parsed.status)\n    ? parsed.status\n    : \"rejected\";\n  const flags = Array.isArray(parsed.flags) ? parsed.flags.map(String) : [];\n  const summary = typeof parsed.summary === \"string\" ? parsed.summary : \"\";","sourceCodeStart":504,"sourceCodeEnd":540,"githubUrl":"https://github.com/midudev/autoskills/blob/0ec725320d2137253ab2e68e7ba8a072148e741a/packages/autoskills/scripts/sync-skills.mjs#L504-L540","documentation":"When the OpenAI chat-completions API responds with a non-2xx status, reviewWithOpenAI reads the response body and throws `OpenAI <status>: <first 200 chars>` so the developer sees the API's own error message (quota exceeded, invalid key, model not found, etc.). It surfaces upstream HTTP failures with truncated context.","triggerScenarios":"POST to the OpenAI API returns res.ok === false — 401 invalid/revoked key, 429 rate limit or insufficient quota, 404 wrong model name, 5xx OpenAI outage. Body text is captured and truncated to 200 chars.","commonSituations":"Expired or revoked OPENAI_API_KEY; billing/quota exhausted on the account; typos or deprecation in the configured model name; very large reviews hitting rate limits (429).","solutions":["Read the status/message: 401 → fix OPENAI_API_KEY; 429 → wait and retry or add credits; 404 → fix the model name","Verify the API key works: curl https://api.openai.com/v1/models with the Bearer token","Check billing/quota at platform.openai.com and top up if needed","Add retry-with-backoff around review for transient 429/5xx, or skip with --no-review"],"exampleFix":"// before\nconst res = await fetch(url, { headers, body: JSON.stringify({ model: \"gpt-4-turbo-preview\", ... }) }); // 404: model retired\n// after\nconst res = await fetch(url, { headers, body: JSON.stringify({ model: \"gpt-4o\", ... }) }); // valid model","handlingStrategy":"retry","validationCode":"// validate the key and model before the review call\nconst keyCheck = await fetch(\"https://api.openai.com/v1/models\", { headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}` } });\nif (!keyCheck.ok) throw new Error(`OpenAI key invalid or quota exceeded: ${keyCheck.status}`);","typeGuard":null,"tryCatchPattern":"try {\n  await reviewWithOpenAI(skillName, files);\n} catch (err) {\n  const m = err.message.match(/^OpenAI (\\d{3}):/);\n  if (m) {\n    const status = Number(m[1]);\n    if (status === 401) console.error(\"Fix OPENAI_API_KEY\");\n    else if (status === 429) await retryWithBackoff(() => reviewWithOpenAI(skillName, files));\n    else if (status === 404) console.error(\"Model name invalid/retired — update configuration\");\n  } else throw err;\n}","preventionTips":["Probe /v1/models with the key before batch reviews","Keep the model name current — retired models return 404","Add exponential backoff for 429/5xx responses","Monitor billing/quota on platform.openai.com to avoid 429 insufficient_quota"],"tags":["http","openai","api","upstream"],"backgroundTag":"upstream-api-error","analyzedSha":"0ec725320d2137253ab2e68e7ba8a072148e741a","analyzedAt":"2026-09-15T14:12:31.090Z","contentChangedAt":"2026-09-15T14:12:31.090Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}