jackwener/OpenCLI · error · ArgumentError
upwork sort must be one of ${Array.from(SORT_VALUES).join('
Error message
upwork sort must be one of ${Array.from(SORT_VALUES).join(' / ')}, got "${value}" What it means
requireSort validates the sort option against SORT_VALUES = {recency, relevance, client_total_charge, client_total_reviews}. Any other value throws ArgumentError listing the allowed sort keys.
Source
Thrown at clis/upwork/utils.js:99
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;
}
/**
* Build the Upwork search URL. Only forwards filters the user actually
* supplied so the URL stays canonical and round-trippable.
*/
export function buildSearchUrl({ query, location, category, sort, page, perPage }) {
const params = new URLSearchParams();
params.set('q', query);
if (location) params.set('location', location);
if (category) params.set('category2_uid', category);
if (sort && sort !== 'recency') params.set('sort', sort);
if (perPage && perPage !== 10) params.set('per_page', String(perPage));
if (page && page > 1) params.set('page', String(page));
return `${UPWORK_ORIGIN}/nx/search/jobs/?${params.toString()}`;
}View on GitHub (pinned to 49907e53dc)
Solutions
- Use one of: recency, relevance, client_total_charge, client_total_reviews
- Omit --sort to use the default 'recency'
- Check --help output for the current list of supported sort values
Example fix
// before $ opencli upwork search "vue" --sort clientTotalCharge // after $ opencli upwork search "vue" --sort client_total_charge
Defensive patterns
Strategy: validation
Validate before calling
const SORTS = ['recency','relevance','client_total_charge','client_total_reviews'];
function isValidSort(s) {
return SORTS.includes(String(s ?? '').trim().toLowerCase());
} Type guard
function isSortValue(v) {
return ['recency','relevance','client_total_charge','client_total_reviews'].includes(v);
} Try / catch
try {
await search({ q, sort });
} catch (e) {
if (e instanceof ArgumentError && /sort must be one of/.test(e.message)) {
return search({ q, sort: 'recency' });
}
throw e;
} Prevention
- Use the snake_case keys exactly as documented
- Check --help for the supported sort list per version
- Don't assume camelCase or web-UI sort names work
When it happens
Trigger: Calling a search/feed command with --sort set to an unsupported key like 'date', 'rating', or 'client_hire_rate'; typo in one of the snake_case keys (e.g. 'client total charges').
Common situations: Using sort names from the Upwork web UI's dropdown which don't match the API keys; assuming camelCase ('clientTotalCharge') works; stale scripts referencing a sort key that was removed or renamed.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- upwork tab must be one of ${Object.keys(FEED_TABS).join(' /
- ${label} must be one of: ${Object.keys(choices).join(', ')}
- ${label} must be one of: ${choices.join(', ')}
- unsupported notification type: ${value}
- upwork ${label} must be >= ${min}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/79c991373bc7f6e5.
Report an issue: GitHub.