affaan-m/ECC · error · Error
invalid discussion id
Error message
invalid discussion id
What it means
announcementKey validates the discussion id against /^[A-Za-z0-9_-]+$/ (alphanumerics, underscore, hyphen only) and throws 'invalid discussion id' on failure. Discussion ids from the GitHub API are numeric strings, so any other shape means the value was corrupted, decorated with prefixes, or never supplied.
Solutions
- Pass the raw numeric discussion id as a string, e.g. String(discussion.id) from the GraphQL discussion node, not a URL or prefixed value.
- Strip prefixes/fragments before calling: discussionId.replace(/^.*[#/]/, '').
- Verify the discussion lookup succeeded (non-null) before building the key.
- Trim whitespace and confirm with /\d+/ as a pre-check.
Example fix
// before
const key = announcementKey({ repository, discussionId: 'https://github.com/owner/repo/discussions/42#discussion-42' });
// after
const id = String(discussion.id); // e.g. '42' from the API node
const key = announcementKey({ repository, discussionId: id }); Defensive patterns
Strategy: validation
Validate before calling
const isValidDiscussionId = (id) => typeof id === 'string' && /^[A-Za-z0-9_-]+$/.test(id.trim());
if (!isValidDiscussionId(rawId)) throw new Error('discussionId must be a bare id string'); Type guard
const isDiscussionId = (v) => typeof v === 'string' && /^[A-Za-z0-9_-]+$/.test(v);
Try / catch
try {
const key = announcementKey({ repository, discussionId });
} catch (err) {
if (err.message === 'invalid discussion id') {
console.error(`discussionId must be a bare id (got ${JSON.stringify(discussionId)})`);
}
throw err;
} Prevention
- Always use String(discussion.id) from the GraphQL node, never a URL or title.
- Strip '#' fragments and prefixes when ids originate from user input.
- Confirm the discussion lookup returned a non-null result before key-building.
- Trim whitespace from ids that pass through config or env.
When it happens
Trigger: main() supplies discussionId as a URL ('.../discussions/42'), a '#123' or 'D123' prefixed value, a value containing spaces, or undefined when the discussion lookup failed and callers proceed to key-building anyway.
Common situations: Copying a discussion URL fragment including '#'; storing the id with formatting characters; a failed findReleaseDiscussion returning null that gets stringified into 'null'.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- invalid repository
- invalid cron expression
- Invalid format: . Use text or json.
- invalid issueNumber: expected positive integer, got
- invalid repo: expected non-empty string, got
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/c5e920c41f91b470.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/discord/announcement-core.mjs:25
}
export function releaseMarker(tag) {
const normalized = String(tag || '').trim();
if (!normalized) throw new Error('release tag is required');
return `<!-- ecc-release:${normalized} -->`;
}
export function findReleaseDiscussion(discussions, marker) {
return discussions.find(item => (
item?.category?.name === 'Announcements'
&& typeof item.body === 'string'
&& item.body.includes(marker)
)) || null;
}
export function announcementKey({ repository, discussionId }) {
if (!/^[^/\s]+\/[^/\s]+$/.test(String(repository || ''))) throw new Error('invalid repository');
if (!/^[A-Za-z0-9_-]+$/.test(String(discussionId || ''))) throw new Error('invalid discussion id');
return `${repository}:discussion:${discussionId}`;
}
export function buildDiscordPayload({ title, body, url, key }) {
const discussionId = String(key).split(':').at(-1);
const footer = `ecc:${discussionId}`;
const description = String(body || '').trim().slice(0, DISCORD_DESCRIPTION_LIMIT);
const nonce = `ecc-${createHash('sha256').update(String(key)).digest('hex').slice(0, 16)}`;
return {
allowed_mentions: { parse: [] },
nonce,
enforce_nonce: true,
embeds: [{
title: String(title || 'ECC announcement').trim().slice(0, 256),
description,
url: String(url || ''),
footer: { text: footer },
}],View on GitHub (pinned to 8321021c54)