{"record":{"id":"d76721727023c844","repo":"affaan-m/ECC","slug":"invalid-discord-webhook-url","errorCode":null,"errorMessage":"invalid Discord webhook URL","messagePattern":"invalid Discord webhook URL","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/discord/announcement-core.mjs","lineNumber":58,"sourceCode":"      description,\n      url: String(url || ''),\n      footer: { text: footer },\n    }],\n  };\n}\n\nexport function findDiscordReceipt(messages, key) {\n  const discussionId = String(key).split(':').at(-1);\n  return messages.find(message => message.embeds?.some(embed => embed.footer?.text === `ecc:${discussionId}`)) || null;\n}\n\nexport function normalizeDiscordWebhookUrl(value) {\n  const raw = String(value || '').trim();\n  let parsed;\n  try {\n    parsed = new URL(raw);\n  } catch {\n    throw new Error('invalid Discord webhook URL');\n  }\n  if (parsed.protocol !== 'https:' || parsed.hostname !== 'discord.com' || parsed.port || parsed.username || parsed.password || parsed.search || parsed.hash) {\n    throw new Error('invalid Discord webhook URL');\n  }\n  if (!/^\\/api\\/webhooks\\/\\d{10,25}\\/[A-Za-z0-9._-]{20,}$/.test(parsed.pathname)) {\n    throw new Error('invalid Discord webhook URL');\n  }\n  parsed.search = '?wait=true';\n  return parsed.toString();\n}\n\nexport function discussionReceiptMarker(key) {\n  return `<!-- ecc-discord-receipt:${createHash('sha256').update(String(key)).digest('hex').slice(0, 32)} -->`;\n}\n\nexport function findDiscussionReceipt(comments, marker) {\n  const trusted = comments.filter(comment => (\n    ['github-actions', 'github-actions[bot]'].includes(comment?.author?.login)","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/affaan-m/ECC/blob/06c5e118c4d3e6c3b7f9445f973a2194c82de193/scripts/discord/announcement-core.mjs#L40-L76","documentation":"normalizeDiscordWebhookUrl parses the configured webhook and rejects anything that is not an https URL on discord.com — protecting against SSRF and credential leakage to arbitrary hosts. Parse failure, wrong protocol, or wrong host all land here.","triggerScenarios":"Triggered when announcement-core.mjs rejects the current invocation: invalid Discord webhook URL","commonSituations":"Occurs while running scripts/discord/announcement-core.mjs with invalid arguments, missing flags, or a failing external dependency; the guard at scripts/discord/announcement-core.mjs:58 aborts the command with this message.","solutions":["Correct the value to one of the accepted options listed in the error message."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"06c5e118c4d3e6c3b7f9445f973a2194c82de193","analyzedAt":"2026-08-18T11:27:13.915Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}