affaan-m/ECC · error · Error
discussion number is invalid
Error message
discussion number is invalid
What it means
discussionFromGitHub throws this before making any network call when DISCUSSION_NUMBER is not a string of digits. The regex /^\d+$/ guards the REST URL construction, since a non-numeric number would produce a malformed endpoint and a confusing 404/400 from GitHub.
Solutions
- Set DISCUSSION_NUMBER to the bare numeric discussion id (e.g. 12)
- Strip a leading '#' and extract the number if you only have a URL: DISCUSSION_NUMBER=$(basename "$DISCUSSION_URL")
- Confirm the env var is exported and reachable inside the script's process
- Echo the value in CI to see exactly what the script receives
Example fix
// before
if (!/^\d+$/.test(env.DISCUSSION_NUMBER || '')) throw new Error('discussion number is invalid');
// after
const rawNumber = (env.DISCUSSION_NUMBER || '').trim().replace(/^#/, '');
if (!/^\d+$/.test(rawNumber)) throw new Error(`discussion number is invalid: "${env.DISCUSSION_NUMBER}"`); Defensive patterns
Strategy: validation
Validate before calling
const raw = (process.env.DISCUSSION_NUMBER || '').trim().replace(/^#/, '');
if (!/^\d+$/.test(raw)) throw new Error(`DISCUSSION_NUMBER must be numeric, got: ${process.env.DISCUSSION_NUMBER}`); Type guard
function isValidDiscussionNumber(v) {
return typeof v === 'string' && /^\d+$/.test(v.trim());
} Try / catch
try {
const discussion = await discussionFromGitHub();
} catch (err) {
if (err.message === 'discussion number is invalid') {
console.error(`DISCUSSION_NUMBER="${process.env.DISCUSSION_NUMBER}" — pass the bare numeric id, not a URL`);
}
throw err;
} Prevention
- Pass the plain numeric discussion number in CI (extract from URL via basename if needed)
- Never paste full discussion URLs or '#12' style refs into DISCUSSION_NUMBER
- Echo the env value in the workflow step for debugging
- Add inline normalization (trim, strip leading '#') before the regex
When it happens
Trigger: DISCUSSION_NUMBER env var is empty, unset, contains non-digit characters (e.g. a full URL like https://github.com/owner/repo/discussions/12, a '#12' reference, or trailing whitespace).
Common situations: Workflow passes the discussion URL instead of its number; value pasted with a leading '#' or spaces; DISCUSSION_NUMBER not exported in the job step; typo setting it to the issue number of a different entity.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- must be an absolute path explicitly configured by the…
- -32602
- a claim token is required
- a confirmed nonempty coordinate is required
- a generated candidate cannot claim original-source identity
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/42187cf70b8bd50b.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/discord/release-announce.mjs:95
const created = await githubGraphql(
`mutation($repo:ID!,$cat:ID!,$title:String!,$body:String!){createDiscussion(input:{repositoryId:$repo,categoryId:$cat,title:$title,body:$body}){discussion{id title body url category{name}}}}`,
{ repo: repository.id, cat: category.id, title, body },
);
return created.createDiscussion.discussion;
}
function discussionFromEnvironment() {
if (env.DISCUSSION_CATEGORY !== 'Announcements') throw new Error('discussion is not an Announcement');
return {
id: env.DISCUSSION_ID,
title: env.DISCUSSION_TITLE,
body: env.DISCUSSION_BODY,
url: env.DISCUSSION_URL,
};
}
async function discussionFromGitHub() {
if (!/^\d+$/.test(env.DISCUSSION_NUMBER || '')) throw new Error('discussion number is invalid');
const response = await request(`https://api.github.com/repos/${env.GITHUB_REPOSITORY}/discussions/${env.DISCUSSION_NUMBER}`, {
headers: { Authorization: `Bearer ${env.GITHUB_TOKEN}`, Accept: 'application/vnd.github+json' },
});
if (!response.ok) throw new Error(`discussion lookup failed (${response.status})`);
const discussion = await response.json();
if (discussion.category?.name !== 'Announcements') throw new Error('discussion is not an Announcement');
return { id: discussion.node_id, title: discussion.title, body: discussion.body, url: discussion.html_url };
}
async function findReceiptComment(discussionId, marker) {
let cursor = null;
for (let page = 0; page < 50; page += 1) {
const data = await githubGraphql(
`query($id:ID!,$after:String){node(id:$id){... on Discussion{comments(first:100,after:$after){nodes{id body author{login}} pageInfo{hasNextPage endCursor}}}}}`,
{ id: discussionId, after: cursor },
);
const comments = data.node?.comments;
if (!comments) throw new Error('discussion receipt lookup failed');View on GitHub (pinned to 8321021c54)