jackwener/OpenCLI · error · ArgumentError

upwork job id is required

Error message

upwork job id is required

What it means

requireCiphertext validates Upwork job ids, which must be ciphertext of the form ~01… or ~02… followed by digits. This empty-input branch throws ArgumentError when the id argument is missing, empty, or whitespace after String() coercion and trim().

Source

Thrown at clis/upwork/utils.js:79

    }
    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();
    if (!id) throw new ArgumentError('upwork job id is required');
    const urlMatch = id.match(/~0[12]\d+/);
    if (urlMatch) id = urlMatch[0];
    if (!CIPHERTEXT_PATTERN.test(id)) {
        throw new ArgumentError(`upwork job id "${value}" is not a valid ciphertext (expected ~01… or ~02… followed by digits)`);
    }
    return id;
}

export function requireFeedTab(value, defaultValue = 'best-matches') {
    const v = String(value ?? defaultValue).trim().toLowerCase();
    if (!FEED_TABS[v]) {
        throw new ArgumentError(`upwork tab must be one of ${Object.keys(FEED_TABS).join(' / ')}, got "${value}"`);
    }
    return v;
}

export function requireSort(value, defaultValue = 'recency') {
    const v = String(value ?? defaultValue).trim().toLowerCase();

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a job id like ~02abc123... as the argument
  2. Verify the upstream variable/pipe actually contains a value before invoking
  3. Capture an id from a list/search command's round-trippable rows first

Example fix

// before
const id = process.env.JOB_ID; // unset -> ''
await show(id); // upwork job id is required
// after
if (!process.env.JOB_ID) throw new Error('JOB_ID not set');
await show(process.env.JOB_ID);
Defensive patterns

Strategy: validation

Validate before calling

function hasJobId(v) {
  return typeof v === 'string' && v.trim().length > 0;
}
if (!hasJobId(id)) throw new Error('job id required before calling detail');

Type guard

function isNonEmptyString(v) {
  return typeof v === 'string' && v.trim().length > 0;
}

Try / catch

try {
  await show(id);
} catch (e) {
  if (e instanceof ArgumentError && e.message === 'upwork job id is required') {
    console.error('JOB_ID env/arg missing');
    process.exitCode = 2;
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the detail/show command with no id argument, an empty string '', null/undefined (String(null ?? '') = ''), or a value consisting only of spaces.

Common situations: Scripting the detail command from a variable that was never populated; piping an empty row from another command; forgetting the positional argument; shell variable unset ($ID expands to empty).

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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