jackwener/OpenCLI · error · CommandExecutionError

Xiaoyuzhou history returned an invalid ${label}; expected se

Error message

Xiaoyuzhou history returned an invalid ${label}; expected seconds

What it means

This CommandExecutionError is thrown by optionalSeconds when a numeric seconds field from the Xiaoyuzhou API (episode.duration, required positive; row.progress, allowed >= 0) is not a safe integer or is below its minimum (duration must be >= 1). The field may legitimately be null, but any present value must be a whole number of seconds.

Source

Thrown at clis/xiaoyuzhou/history.js:42

function requiredId(value, label) {
    if (typeof value !== 'string' || !XIAOYUZHOU_ID.test(value)) {
        throw new CommandExecutionError(`Xiaoyuzhou history returned an invalid ${label}`);
    }
    return value.toLowerCase();
}

function requiredString(value, label) {
    if (typeof value !== 'string' || !value.trim()) {
        throw new CommandExecutionError(`Xiaoyuzhou history returned an invalid ${label}`);
    }
    return value.trim();
}

function optionalSeconds(value, label, { positive = false } = {}) {
    if (value === null) return null;
    if (!Number.isSafeInteger(value) || value < (positive ? 1 : 0)) {
        throw new CommandExecutionError(`Xiaoyuzhou history returned an invalid ${label}; expected seconds`);
    }
    return value;
}

function optionalIsoTime(value, label, { required = false } = {}) {
    if (value === null) {
        if (required) throw new CommandExecutionError(`Xiaoyuzhou history returned a missing ${label}`);
        return null;
    }
    if (typeof value !== 'string' || !value.includes('T') || !Number.isFinite(Date.parse(value))) {
        throw new CommandExecutionError(`Xiaoyuzhou history returned an invalid ${label}`);
    }
    return new Date(value).toISOString();
}

function parseHistoryPage(response) {
    if (!isRecord(response) || !isRecord(response.raw) || response.raw.data !== response.data) {
        throw new CommandExecutionError('Xiaoyuzhou history returned an unexpected response shape');

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Update the library/CLI to a version matching the current API field types.
  2. Inspect the raw payload to see the actual type/format of duration or progress (float? string? ISO-8601 duration?).
  3. If the API now returns milliseconds, convert before parsing (Math.round(ms / 1000)) via a wrapper around requestXiaoyuzhouJson.
  4. Convert string numerics to Number() in a pre-processing pass if a proxy is responsible.
  5. Report the changed payload shape to maintainers.

Example fix

// before (API returns ms floats)
{ "episode": { "duration": 3720000.5 } }
// after (normalize before parse)
{ "episode": { "duration": Math.round(raw.duration / 1000) } } // 3720
Defensive patterns

Strategy: type-guard

Validate before calling

function isSeconds(v, { positive = false } = {}) { return v === null || (Number.isSafeInteger(v) && v >= (positive ? 1 : 0)); }
if (!isSeconds(ep.duration, { positive: true }) || !isSeconds(row.progress)) throw new Error('Unexpected seconds field');

Type guard

const isSafeSeconds = (v, min) => typeof v === 'number' && Number.isSafeInteger(v) && v >= min;

Try / catch

try { const rows = await fetchHistory(); } catch (e) { if (e instanceof CommandExecutionError && e.message.includes('expected seconds')) { console.error('duration/progress is not integer seconds — check for ms floats or string values'); } else throw e; }

Prevention

When it happens

Trigger: parseHistoryEpisode calls optionalSeconds(episode.duration, ..., { positive: true }) and parseProgressRows calls optionalSeconds(row.progress, ...); the error fires when the value is a float (e.g. 12.5), a string like "300", undefined, negative, or exceeds Number.MAX_SAFE_INTEGER — only literal null passes through as null.

Common situations: API version change switching duration from integer seconds to float milliseconds; proxies/mocks returning strings for numeric fields; a new field type (ISO 8601 duration string like PT1H2M3S) replacing raw seconds.

Related errors


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