jackwener/OpenCLI · error · ArgumentError

xianyu publish ${label} must be a positive price with at mos

Error message

xianyu publish ${label} must be a positive price with at most 2 decimals

What it means

parsePositivePrice() validates an optional price string for `xianyu publish`. If a non-empty price is given that doesn't match /^\d+(?:\.\d{1,2})?$/ (positive decimal with at most 2 fraction digits), ArgumentError `xianyu publish ${label} must be a positive price with at most 2 decimals` is thrown at clis/xianyu/publish.js:40. This enforces Goofish's price format up front.

Source

Thrown at clis/xianyu/publish.js:40

    }
    return buildPublishUrl();
}

function requireText(value, label) {
    const text = String(value ?? '').replace(/\s+/g, ' ').trim();
    if (!text) {
        throw new ArgumentError(`xianyu publish ${label} cannot be empty`);
    }
    return text;
}

function parsePositivePrice(value, label) {
    if (value == null || String(value).trim() === '') {
        return null;
    }
    const text = String(value).trim();
    if (!/^\d+(?:\.\d{1,2})?$/.test(text)) {
        throw new ArgumentError(`xianyu publish ${label} must be a positive price with at most 2 decimals`);
    }
    const price = Number(text);
    if (!Number.isFinite(price) || price <= 0) {
        throw new ArgumentError(`xianyu publish ${label} must be a positive price`);
    }
    return text;
}

function validateCondition(value) {
    const condition = requireText(value, 'condition');
    if (!CONDITION_CHOICES.includes(condition)) {
        throw new ArgumentError(`xianyu publish condition must be one of: ${CONDITION_CHOICES.join(', ')}`);
    }
    return condition;
}

function validateImagePaths(raw) {
    if (!raw) return [];

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Normalize the price before calling: strip currency symbols, replace ',' with '.', and format to at most 2 decimals (e.g. parseFloat(...).toFixed(2)).
  2. Remove thousand separators/commas that aren't decimal markers.
  3. Ensure the value is positive; omit the field (null/'') entirely if no price should be set.
  4. Add a regex pre-check /^^?\d+(\.\d{1,2})?$/ in your caller with a friendly error.

Example fix

// before
await publish({ title, price: rawPrice }); // rawPrice = '¥1,299.00' → ArgumentError

// after
const price = rawPrice == null ? null : parseFloat(String(rawPrice).replace(/[^\d.]/g, '')).toFixed(2);
await publish({ title, price });
Defensive patterns

Strategy: validation

Validate before calling

const PRICE_RE = /^\d+(?:\.\d{1,2})?$/;
if (price != null && String(price).trim() !== '' && !PRICE_RE.test(String(price).trim())) {
  throw new Error(`price must match d+.dd (got ${price})`);
}

Type guard

function isValidPrice(v) { return v == null || String(v).trim() === '' || /^\d+(?:\.\d{1,2})?$/.test(String(v).trim()); }

Try / catch

try {
  await publish({ title, price });
} catch (e) {
  if (e instanceof ArgumentError && /positive price/.test(e.message)) {
    price = parseFloat(String(price).replace(/[^\d.]/g, '')).toFixed(2); // normalize and retry once
    return publish({ title, price });
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing prices like '12,50' (comma decimal), '¥100' or '$5' (currency symbols), '-3' (negative), '12.999' (3 decimals), '1e3' (scientific), or ' 12 ' variants that fail the strict regex. Null/empty passes through as null (no price).

Common situations: Parsing prices from scraped text or spreadsheets that include currency symbols or thousand separators; locales using comma as decimal separator; user input passed straight through without normalization; storing prices as floats formatted with extra precision.

Related errors


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