{"record":{"id":"f479fc6eb021b3fa","repo":"tinyhumansai/openhuman","slug":"openai-responses-api-failed-response-status","errorCode":null,"errorMessage":"OpenAI Responses API failed (${response.status}): ${message}","messagePattern":"OpenAI Responses API failed \\((.+?)\\): (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/release/generate-release-notes.mjs","lineNumber":509,"sourceCode":"    if (error?.name === 'AbortError') {\n      throw new Error(`OpenAI Responses API timed out after ${timeoutMs}ms`);\n    }\n    throw error;\n  } finally {\n    clearTimeout(timeout);\n  }\n\n  const body = await response.text();\n  let json = null;\n  try {\n    json = JSON.parse(body);\n  } catch {\n    // Keep the raw body in the error below.\n  }\n\n  if (!response.ok) {\n    const message = json?.error?.message || body;\n    throw new Error(`OpenAI Responses API failed (${response.status}): ${message}`);\n  }\n\n  const text = extractResponseText(json);\n  if (!text) {\n    throw new Error('OpenAI response did not contain output text');\n  }\n  return text;\n}\n\nexport function renderDeterministicNotes({ title, payload }) {\n  const newContributors = payload.contributors.filter((contributor) => contributor.isNew);\n  const newContributorsSection = newContributors.length\n    ? `\n## New Contributors 🌟\n\n${newContributors.map((contributor) => renderNewContributorLine(contributor, payload.pullRequests)).join('\\n')}\n\nHope you join the Discord for exclusive roles and contributor rewards!","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/release/generate-release-notes.mjs#L491-L527","documentation":"OpenAI answered the Responses API call with a non-2xx HTTP status; the script surfaces the status code plus the error.message from the JSON body, falling back to the raw body when it is not JSON.","triggerScenarios":"401/403 from a revoked, mistyped, or region-blocked OPENAI_API_KEY; 429 from rate limits or exhausted org quota; 400 from an invalid --model / OPENAI_MODEL value (default gpt-5.2); 5xx during an OpenAI incident.","commonSituations":"Expired CI secret; org hit its spend limit; OPENAI_MODEL pointing at a chat/completions-era name the Responses API rejects; key from a free tier without Responses API access.","solutions":["Map the status: 401/403 → fix the key; 429 → wait, retry, check org billing; 400 → check the --model value; 5xx → retry later","Verify the key independently: curl -s -o /dev/null -w '%{http_code}' -H 'Authorization: Bearer $OPENAI_API_KEY' https://api.openai.com/v1/models","Use --no-ai if the release cannot wait on OpenAI"],"exampleFix":"# before\nOPENAI_MODEL=some-chat-completions-name node scripts/release/generate-release-notes.mjs   # 400: unknown model\n\n# after — use the default or a valid Responses model\nnode scripts/release/generate-release-notes.mjs --model gpt-5.2","handlingStrategy":"try-catch","validationCode":"# cheap key liveness check before the long generation call\ncurl -sf -o /dev/null -H \"Authorization: Bearer $OPENAI_API_KEY\" https://api.openai.com/v1/models \\\n  || { echo 'OpenAI key invalid or network down' >&2; exit 1; }","typeGuard":null,"tryCatchPattern":"out=$(node scripts/release/generate-release-notes.mjs --from \"$FROM\" 2>&1)\ncase \"$out\" in\n  *'failed (401)'*|*'failed (403)'*) echo 'fatal: bad key' >&2; exit 2 ;;\n  *'failed (429)'*|*'failed (5'*)   sleep 60; node scripts/release/generate-release-notes.mjs --from \"$FROM\" ;;\n  *) printf '%s\\n' \"$out\" ;;\nesac","preventionTips":["rotate expiring keys before they die mid-release","keep billing/limit alerts on the OpenAI org","classify 429/5xx as retryable and 401/400 as fatal in wrappers"],"tags":["openai","http","api-errors","authentication"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}