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

  1. 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.
  2. Strip prefixes/fragments before calling: discussionId.replace(/^.*[#/]/, '').
  3. Verify the discussion lookup succeeded (non-null) before building the key.
  4. 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

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


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)