affaan-m/ECC · error

invalid issueNumber: expected positive integer, got

Error message

invalid issueNumber: expected positive integer, got ${JSON.stringify(issueNumber)}

What it means

assertValidIssueNumber validates the issue identifier before any GitHub operation. It must be a finite positive integer; NaN, Infinity, zero, negatives, floats, and non-numeric values are rejected. Every action that mutates or inspects a specific issue (claim, validate, publish, review, decompose) runs this guard first.

Solutions

  1. Coerce and validate the issue number: Number(value) and Number.isInteger check before calling
  2. Extract the number with a strict pattern, e.g. /#?(\d+)$/ on the issue reference
  3. Ensure CLI/config sources supply the raw numeric value, not a URL or string
  4. Fix parseInt fallbacks so failures produce a clear error instead of NaN downstream

Example fix

// before
applyClaim(repo, parseInt(arg, 10), {}) // NaN when arg is '#abc'
// after
const m = /#?(\d+)$/.exec(String(arg));
if (!m) throw new Error(`bad issue ref: ${arg}`);
applyClaim(repo, Number(m[1]), {})
Defensive patterns

Strategy: type-guard

Validate before calling

function assertIssueNumber(n) { if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) throw new Error(`bad issue number: ${JSON.stringify(n)}`); }
assertIssueNumber(issueNumber);

Type guard

const isIssueNumber = (v) => typeof v === 'number' && Number.isInteger(v) && v > 0 && Number.isFinite(v);

Try / catch

try { applyPublish(repo, n, opts); } catch (e) { if (String(e.message).startsWith('invalid issueNumber')) console.error('issue number came from a bad parse; extract digits strictly'); throw e; }

Prevention

When it happens

Trigger: Calling applyClaim/applyValidate/applyPublish/applyReview/applyDecompose with issueNumber from parseInt of a non-numeric string (NaN), a string like '42', a float like 42.5, or 0/-1 from a failed parse.

Common situations: Parsing an issue URL with a regex that captures extra text; CLI argument '--issue abc'; reading an issue number from a branch name where the prefix isn't stripped; JSON config containing the issue number as a string.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/0045097ade6d8beb. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/github-coordination/actions.js:27

  buildIssueStateFromAction,
  desiredLabelsForState,
  getCoordinationState,
  summarizeStateForOutput,
  syncIssueLabels,
  verifyDependenciesClosed,
} = require('./state');
const { upsertCoordinationWorkItem } = require('./store');
const { extractIssueReferences, extractTasks } = require('./parsing');

function assertValidRepo(repo) {
  if (typeof repo !== 'string' || !repo.trim()) {
    throw new Error(`invalid repo: expected non-empty string, got ${JSON.stringify(repo)}`);
  }
}

function assertValidIssueNumber(issueNumber) {
  if (!Number.isFinite(issueNumber) || issueNumber <= 0 || !Number.isInteger(issueNumber)) {
    throw new Error(`invalid issueNumber: expected positive integer, got ${JSON.stringify(issueNumber)}`);
  }
}

function staleCoordinationLabels(issue, nextLabels, policy) {
  const epicLabel = policy.labels && policy.labels.epic;
  return normalizeLabels(issue.labels).filter(l =>
    (l.startsWith('coordination:') || l === epicLabel) && !nextLabels.includes(l)
  );
}

// applyClaim performs a read (getIssue) → check (assertIssueClaimable) → write
// (editIssue) sequence that is NOT atomic. Two concurrent callers can both read
// an unclaimed issue, pass the check, and both succeed — resulting in a
// double-claim. A code-review finding suggested fixing this via
// context.store.acquireLock(repo, issueNumber), but that API does not exist in
// store.js; adding a call to it would throw at runtime. Left as-is until a
// locking primitive is available — callers should prevent races via external
// serialization (e.g. a serialized job queue or GitHub branch-protection rule).

View on GitHub (pinned to 8321021c54)