jackwener/OpenCLI · error · ArgumentError

upwork ${label} must be a positive integer

Error message

upwork ${label} must be a positive integer

What it means

An ArgumentError thrown by requirePositiveInt when a numeric option (page number, per-page count, etc.) is not a finite integer greater than zero. coerceInt is applied to the raw value (or the default when undefined) and the result must be a positive integer. It guards pagination math against NaN, zero, negatives, and non-numeric strings.

Source

Thrown at clis/upwork/utils.js:60

}

function coerceInt(value) {
    if (value === undefined || value === null || value === '') return NaN;
    const n = typeof value === 'number' ? value : Number(value);
    return Number.isFinite(n) && Number.isInteger(n) ? n : NaN;
}

export function requireQuery(value, label = 'query') {
    const q = String(value ?? '').trim();
    if (!q) throw new ArgumentError(`upwork ${label} cannot be empty`);
    return q;
}

export function requirePositiveInt(value, defaultValue, label) {
    const raw = value ?? defaultValue;
    const n = coerceInt(raw);
    if (!Number.isInteger(n) || n <= 0) {
        throw new ArgumentError(`upwork ${label} must be a positive integer`);
    }
    return n;
}

export function requireBoundedInt(value, defaultValue, min, max, label) {
    const n = requirePositiveInt(value, defaultValue, label);
    if (n < min) throw new ArgumentError(`upwork ${label} must be >= ${min}`);
    if (n > max) throw new ArgumentError(`upwork ${label} must be <= ${max}`);
    return n;
}

/**
 * Upwork job ids are the ciphertext form starting with `~01` or `~02`
 * (the encoded uid surfaced everywhere in URLs and search results).
 * Accepts a bare ciphertext or a full `/jobs/~02…` URL.
 */
export function requireCiphertext(value) {
    let id = String(value ?? '').trim();

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a positive integer (1-based) for the option.
  2. Validate/clamp the value before calling: Number.isInteger(n) && n > 0.
  3. If pages are produced from zero-based user input, add 1 before passing.
  4. Fix the upstream computation that is producing NaN or a float.

Example fix

// before
await cli.search('react developer', { pageNum: 0 }) // ArgumentError
// after
const pageNum = Math.max(1, Math.trunc(Number(userPage) || 1));
await cli.search('react developer', { pageNum })
Defensive patterns

Strategy: validation

Validate before calling

function toPositiveInt(v) {
  const n = typeof v === 'number' ? v : Number(v);
  return Number.isFinite(n) && Number.isInteger(n) && n > 0 ? n : null;
}
// before the call:
const pageNum = toPositiveInt(rawPage);
if (pageNum === null) throw new Error('pageNum must be a positive integer');

Type guard

function isPositiveInt(v) {
  return typeof v === 'number' && Number.isInteger(v) && v > 0;
}

Try / catch

try {
  rows = await cli.search(query, { pageNum: rawPage });
} catch (e) {
  if (e.name === 'ArgumentError' && String(e.message).includes('positive integer')) {
    console.error(`Invalid page value: ${JSON.stringify(rawPage)}; use an integer >= 1`);
    process.exitCode = 2;
  } else throw e;
}

Prevention

When it happens

Trigger: Calling an upwork command with pageNum or n set to 0, a negative number, a non-numeric string like 'abc' or '2.5', or NaN - anything where Number(value) does not yield an integer > 0.

Common situations: Passing a float like 1.5 for the page; users supplying 0 or -1 believing pages are zero-indexed; a config file with a string page value; a computed variable that evaluated to NaN before being passed in.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/26b4302ae91dd97b. Report an issue: GitHub.