{"record":{"id":"49730997871f63e0","repo":"affaan-m/ECC","slug":"discord-webhook-request-failed-response-status","errorCode":null,"errorMessage":"Discord webhook request failed (${response.status})","messagePattern":"Discord webhook request failed \\((.+?)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/discord/release-announce.mjs","lineNumber":172,"sourceCode":"    if (existingReceipt) {\n      if (discussionReceiptStatus(existingReceipt) === 'complete') {\n        console.log('announcement already delivered');\n        return;\n      }\n      throw new Error('announcement has a pending receipt; inspect Discord before clearing it');\n    }\n    const claimId = await addReceiptComment(discussion.id, `${marker}\\n\\nDiscord delivery: pending.`);\n    const payload = buildDiscordPayload({ title: discussion.title, body: discussion.body, url: discussion.url, key });\n    delete payload.nonce;\n    delete payload.enforce_nonce;\n    const response = await request(webhookUrl, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify(payload),\n    });\n    if (!response.ok) {\n      await deleteReceiptComment(claimId);\n      throw new Error(`Discord webhook request failed (${response.status})`);\n    }\n    const message = await response.json();\n    await addReceiptComment(discussion.id, `${marker}\\n\\nDiscord delivery: complete (message ${message.id}).`);\n    await deleteReceiptComment(claimId).catch(() => {\n      console.warn('announcement delivered; pending receipt cleanup requires attention');\n    });\n    console.log('announcement delivered by channel webhook');\n    return;\n  }\n  if (!env.DISCORD_BOT_TOKEN || !/^\\d{10,25}$/.test(env.DISCORD_ANNOUNCE_CHANNEL_ID || '')) {\n    throw new Error('Discord announcement credentials are missing or invalid');\n  }\n  const recent = await discord('GET', `/channels/${env.DISCORD_ANNOUNCE_CHANNEL_ID}/messages?limit=100`);\n  const receipt = findDiscordReceipt(recent, key);\n  if (receipt) {\n    await discord('PUT', `/channels/${env.DISCORD_ANNOUNCE_CHANNEL_ID}/pins/${receipt.id}`);\n    console.log('announcement already delivered; pin verified');\n    return;","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/discord/release-announce.mjs#L154-L190","documentation":"After POSTing the announcement payload to the Discord webhook, the script checks response.ok. Any non-2xx status causes it to delete the pending receipt claim (to allow retries) and throw this error containing the HTTP status code.","triggerScenarios":"request(webhookUrl, { method: 'POST', ... }) returns a non-ok response — e.g. 404 (webhook deleted/revoked), 400 (malformed payload), 429 (rate limited), or 401/403.","commonSituations":"Webhook URL revoked from Discord channel settings; message content exceeding Discord limits (embed/body too long); posting faster than Discord's per-webhook rate limit allows.","solutions":["Check the status code in the message: 404/401 means regenerate the webhook URL in Discord channel settings and update DISCORD_ANNOUNCE_WEBHOOK_URL","400: shorten the release body/title so the payload fits Discord limits","429: retry after waiting; Discord rate limits webhooks (~5 req/2s)","Re-run the workflow — the pending receipt was deleted so the run is retryable"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const res = await fetch(webhookUrl, { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify(payload) }); if (!res.ok) console.error(`Webhook returned ${res.status}`);","typeGuard":"const isRetryable = (status) => status === 429 || status >= 500;","tryCatchPattern":"try { await deliver(discussion); } catch (e) { const m = /failed \\((\\d+)\\)/.exec(e.message); if (m && (m[1] === '429' || +m[1] >= 500)) { await sleep(backoff); return deliver(discussion); } throw e; }","preventionTips":["Regenerate webhook URLs if you get 401/404 and update the secret","Keep announcement bodies under Discord's embed/content size limits","Respect Discord rate limits; avoid rapid re-runs","Re-run is safe: the pending receipt claim is deleted on failure"],"tags":["discord","http","webhook"],"backgroundTag":"http-error-response","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}