{"record":{"id":"2337353f3cc2102f","repo":"thedotmack/claude-mem","slug":"discord-api-error-response-status-errortex","errorCode":null,"errorMessage":"Discord API error: ${response.status} - ${errorText}","messagePattern":"Discord API error: (.+?) - (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/discord-release-notify.js","lineNumber":92,"sourceCode":"          },\n        ],\n        footer: {\n          text: 'claude-mem • Persistent memory for Claude Code',\n        },\n        timestamp: new Date().toISOString(),\n      },\n    ],\n  };\n\n  const response = await fetch(webhookUrl, {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify(payload),\n  });\n\n  if (!response.ok) {\n    const errorText = await response.text();\n    throw new Error(`Discord API error: ${response.status} - ${errorText}`);\n  }\n\n  return true;\n}\n\nasync function main() {\n  const version = process.argv[2];\n  const customNotes = process.argv[3];\n\n  if (!version) {\n    console.error('Usage: node scripts/discord-release-notify.js <version> [notes]');\n    console.error('Example: node scripts/discord-release-notify.js v7.4.2');\n    process.exit(1);\n  }\n\n  console.log(`📣 Posting release notification for ${version}...`);\n\n  const webhookUrl = loadEnv();","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/scripts/discord-release-notify.js#L74-L110","documentation":"postToDiscord POSTs an embed payload to the DISCORD_UPDATES_WEBHOOK URL read from .env. If Discord returns a non-2xx (4xx rate-limit/invalid-webhook/auth, 5xx Discord outage), the script reads the response body and throws a combined error. The webhook is fire-and-forget release notification; this error aborts the notification.","triggerScenarios":"Webhook URL revoked or malformed (401/403/404). Rate limited (429) from posting too frequently. Payload exceeds Discord embed limits — title+description over 2000 chars after truncate, or too many fields (400). Discord 5xx outage.","commonSituations":"Webhook rotated in Discord channel settings and .env not updated. Re-running the script rapidly after a release (429). Notes containing content that pushes the embed over limits. Discord temporarily degraded.","solutions":["Verify the webhook URL in .env (DISCORD_UPDATES_WEBHOOK) is current and not revoked — regenerate in Discord and re-test with curl.","If the body mentions 'rate limit' (429), wait the indicated retry_after seconds and re-run; this script posts at most once per release so a one-off retry suffices.","If 400 on embed size, lower the truncate maxLength in cleanNotes/truncate (currently 2000) and ensure fields stay within Discord's limits.","For 5xx, re-run after a short wait — Discord outages are transient."],"exampleFix":"// before\nif (!response.ok) {\n  const errorText = await response.text();\n  throw new Error(`Discord API error: ${response.status} - ${errorText}`);\n}\n\n// after — handle 429 rate limit with its Retry-After header\nif (!response.ok) {\n  if (response.status === 429) {\n    const retryAfter = parseFloat(response.headers.get('retry-after') || '1') * 1000;\n    await new Promise(r => setTimeout(r, retryAfter));\n    return postToDiscord(webhookUrl, version, notes); // one retry\n  }\n  const errorText = await response.text();\n  throw new Error(`Discord API error: ${response.status} - ${errorText}`);\n}","handlingStrategy":"retry","validationCode":"// Validate the webhook shape and a cheap reachability before posting:\nfunction looksLikeDiscordWebhook(url: string): boolean {\n  return /^https:\\/\\/discord(?:app)?\\.com\\/api\\/(?:webhooks|v\\d+\\/webhooks)\\/[0-9]+\\/[A-Za-z0-9_-]+$/.test(url);\n}\nif (!looksLikeDiscordWebhook(webhookUrl)) throw new Error('DISCORD_UPDATES_WEBHOOK is malformed');","typeGuard":"function isDiscordRateLimit(res: Response): boolean {\n  return res.status === 429;\n}","tryCatchPattern":"// main() already wraps postToDiscord in try/catch (discord-release-notify.js:117-123).\n// For 429, honor Retry-After and retry once (see exampleFix). For 4xx auth/not-found,\n// surface the message and exit non-zero — do not retry a revoked webhook.","preventionTips":["Keep DISCORD_UPDATES_WEBHOOK in .env current; rotate via Discord channel settings, then update .env.","Don't post repeatedly in a short window — Discord rate-limits aggressively.","Validate the payload against Discord embed limits (description <= 2000 chars, <= 25 fields) before sending."],"tags":["discord","webhook","network","release","ci"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}