Hmbown/CodeWhale · error · Error

--attempts must be an integer from 1 to 20

Error message

--attempts must be an integer from 1 to 20

What it means

The --attempts option controls how many times the script polls the deployed facts. It must be an integer between 1 and 20 inclusive; anything else (non-integers, 0, negatives, values above 20) throws this error before any network work starts.

Solutions

  1. Pass an integer from 1 to 20, e.g. --attempts 5
  2. If you need more polling, increase --retry-delay-ms or run the script again instead of raising attempts
  3. Verify the shell passes the value as a plain integer without extra characters

Example fix

// before
node compare-deployed-facts.mjs --attempts 0
// after
node compare-deployed-facts.mjs --attempts 3
Defensive patterns

Strategy: validation

Validate before calling

if (!Number.isInteger(attempts) || attempts < 1 || attempts > 20) throw new Error('attempts must be 1..20');

Type guard

const isValidAttempts = (v) => Number.isInteger(v) && v >= 1 && v <= 20;

Try / catch

try { run(args); } catch (e) { if (e.message.includes('--attempts')) { console.error('Use an integer 1-20'); process.exitCode = 2; } else throw e; }

Prevention

When it happens

Trigger: Running with --attempts 0, --attempts 25, --attempts 2.5, or a non-numeric string like --attempts many.

Common situations: Trying to disable retries by passing 0, over-tuning poll counts past the cap, or quoting/parsing mistakes that turn the value into a non-integer.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/5ffc3ade2016f9eb. Report an issue: GitHub.

Appendix: source

Thrown at web/scripts/compare-deployed-facts.mjs:116

async function main() {
  const args = parseArgs(process.argv.slice(2));
  let baseUrl;
  try {
    baseUrl = new URL(args.baseUrl);
  } catch {
    throw new Error(`invalid --base-url: ${args.baseUrl}`);
  }
  if (!/^https?:$/.test(baseUrl.protocol)) {
    throw new Error("--base-url must use http or https");
  }

  const expectedRevision = args.expectedRevision || localRevision();
  if (!expectedRevision || !/^[0-9a-f]{40}$/i.test(expectedRevision)) {
    throw new Error("expected revision must be an exact 40-character Git SHA");
  }
  if (!Number.isInteger(args.attempts) || args.attempts < 1 || args.attempts > 20) {
    throw new Error("--attempts must be an integer from 1 to 20");
  }
  if (!Number.isFinite(args.retryDelayMs) || args.retryDelayMs < 0 || args.retryDelayMs > 30_000) {
    throw new Error("--retry-delay-ms must be between 0 and 30000");
  }

  const facts = buildFacts();
  const expected = {
    sourceRevision: expectedRevision,
    version: facts.version,
    providerCount: facts.providers.length,
    toolCount: facts.toolCount,
    latestPublishedRelease: facts.latestPublishedRelease,
  };
  const endpoint = new URL("/api/facts", baseUrl).toString();
  let last = { error: "not attempted" };
  let differences = [];

  for (let attempt = 1; attempt <= args.attempts; attempt += 1) {

View on GitHub (pinned to 433685b202)