jackwener/OpenCLI · error · ArgumentError
upwork job id "${value}" is not a valid ciphertext (expected
Error message
upwork job id "${value}" is not a valid ciphertext (expected ~01… or ~02… followed by digits) What it means
requireCiphertext throws this when the provided id (after trimming and extracting a ~0[12]\d+ substring from a possible full URL) does not match CIPHERTEXT_PATTERN /^~0[12]\d{15,21}$/ — i.e. it is not a valid ~01/~02 ciphertext of 16-22 total characters.
Source
Thrown at clis/upwork/utils.js:83
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();
if (!SORT_VALUES.has(v)) {
throw new ArgumentError(`upwork sort must be one of ${Array.from(SORT_VALUES).join(' / ')}, got "${value}"`);
}
return v;View on GitHub (pinned to 49907e53dc)
Solutions
- Copy the full ciphertext id starting with ~01 or ~02 from the job URL or search output
- If you have a job URL, pass the whole URL — the helper extracts the ciphertext automatically
- Check for truncation (needs ~ + '0' + '1'/'2' + 15-21 digits)
- Re-run the search/list command to obtain a fresh round-trippable id
Example fix
// before
await show('17483920'); // numeric uid -> not valid ciphertext
// after
await show('~01a8f3c2d94b7e610253'); Defensive patterns
Strategy: validation
Validate before calling
const CIPHERTEXT = /^~0[12]\d{15,21}$/;
function looksLikeCiphertext(v) {
if (typeof v !== 'string') return false;
const m = v.match(/~0[12]\d+/);
return !!m && CIPHERTEXT.test(m[0]);
}
if (!looksLikeCiphertext(id)) throw new Error('not a ~01/~02 ciphertext id'); Type guard
function isJobCiphertext(v) {
return typeof v === 'string' && /^~0[12]\d{15,21}$/.test(v.trim().match(/~0[12]\d+/)?.[0] ?? '');
} Try / catch
try {
await show(id);
} catch (e) {
if (e instanceof ArgumentError && /not a valid ciphertext/.test(e.message)) {
console.error('Use the ~01…/~02… id from a job URL or list output');
return null;
}
throw e;
} Prevention
- Always copy ids from job URLs or list rows, never numeric uids
- Pass the full /jobs/~02… URL — the helper extracts the id
- Watch for shell/trailing-whitespace truncation when pasting
When it happens
Trigger: Passing a numeric Upwork uid instead of the ciphertext form; passing a truncated or corrupted id (too few digits); passing a URL whose id does not match the pattern; passing an opaque job reference from an old export.
Common situations: Using the internal numeric job id from the API instead of the ciphertext from URLs/search results; copy-paste truncation dropping the `~` or digits; older tooling that stored a different id format.
Related errors
- upwork ${label} must be >= ${min}
- upwork ${label} must be <= ${max}
- archive search sort must be one of ${SORT_OPTIONS.join(', ')
- archive search mediatype must be one of ${MEDIATYPES.join(',
- archive search limit must be a positive integer
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9cee36ad188e2184.
Report an issue: GitHub.