jackwener/OpenCLI · error · ArgumentError

xianyu search ${label} must be a non-negative number

Error message

xianyu search ${label} must be a non-negative number

What it means

parsePriceArg validates the --min-price / --max-price options for `xianyu search`. Because float args arrive as strings, the value is trimmed and coerced with Number(); if the result is not a finite number or is negative, an ArgumentError is thrown. Prices must be non-negative numbers in 元 (yuan), since they are passed server-side as a priceRange search filter.

Source

Thrown at clis/xianyu/search.js:21

const ROWS_PER_PAGE = 30;
const MAX_LIMIT = 60;
function normalizeLimit(value) {
    const n = Number(value);
    if (!Number.isFinite(n))
        return 20;
    return Math.min(MAX_LIMIT, Math.max(1, Math.floor(n)));
}
function buildSearchUrl(query) {
    return `https://www.goofish.com/search?q=${encodeURIComponent(query)}`;
}
// Parse a --min-price / --max-price argument into a non-negative number, or null when omitted.
// (`float` args are not auto-coerced by the framework, so they arrive as strings.)
function parsePriceArg(value, label) {
    if (value === undefined || value === null || value === '')
        return null;
    const n = Number(String(value).trim());
    if (!Number.isFinite(n) || n < 0) {
        throw new ArgumentError(`xianyu search ${label} must be a non-negative number`, `For example: --${label} 100000`);
    }
    return n;
}
// Goofish's PC search applies price filtering server-side via
// propValueStr.searchFilter = "priceRange:<min>,<max>;" (values in 元). An omitted
// bound is filled with a wide default so a single-sided range still works.
function buildSearchFilter(minPrice, maxPrice) {
    if (minPrice == null && maxPrice == null)
        return '';
    const lo = minPrice != null ? minPrice : 0;
    const hi = maxPrice != null ? maxPrice : 99999999;
    return `priceRange:${lo},${hi};`;
}
// Region filtering is server-side via extraFilterValue (a JSON string) carrying a
// divisionList of {province, city} pairs. A city alone (empty province) is accepted,
// as is a province alone (empty city). Returns "{}" when no region is requested.
function buildExtraFilterValue(province, city) {
    if (!province && !city)

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a plain non-negative number, e.g. --min-price 100000 --max-price 500000
  2. Remove currency symbols, commas, and units from the value
  3. Quote shell values containing special characters (e.g. '$100') so they are not mangled
  4. Check that the variable feeding the flag is set and numeric before invoking

Example fix

// before
xianyu search 'iphone' --min-price ¥1,000 --max-price -1
// after
xianyu search 'iphone' --min-price 1000 --max-price 999999
Defensive patterns

Strategy: validation

Validate before calling

function isValidPrice(v){ if(v===undefined||v===null||v==='') return true; const n=Number(String(v).trim()); return Number.isFinite(n)&&n>=0; }
if(!isValidPrice(minPrice)) throw new Error('min-price must be a non-negative number');

Type guard

const isPriceArg = (v) => v === undefined || v === null || v === '' || (Number.isFinite(Number(String(v).trim())) && Number(String(v).trim()) >= 0);

Try / catch

try { await xianyuSearch({ 'min-price': minPrice, 'max-price': maxPrice }); } catch (e) { if (e instanceof ArgumentError && /must be a non-negative number/.test(e.message)) { console.error('Fix the price flag: use a plain non-negative number'); } else throw e; }

Prevention

When it happens

Trigger: Calling `xianyu search` with --min-price or --max-price set to a non-numeric string (e.g. 'abc', '1k', '100 元'), an empty-ish string, or a negative number like '-5'.

Common situations: Copying prices with currency symbols or thousand separators ('¥1,000'), typing '-100' by mistake, passing shell variables that are unset/empty, or assuming the CLI parses '1.5k'-style shorthand.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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