jackwener/OpenCLI · error · CommandExecutionError

${parsed?.message || parsed?.msg || 'Xiaoyuzhou API returned

Error message

${parsed?.message || parsed?.msg || 'Xiaoyuzhou API returned success=false'}

What it means

Some Xiaoyuzhou responses use a success boolean instead of (or in addition to) a numeric code. If parsed.success === false and no code-based failure was already caught, requestXoyuzhouJson throws CommandExecutionError with the API's message/msg field or a fallback string. This guards against bodies that are valid JSON with a passing code but explicitly marked unsuccessful.

Source

Thrown at clis/xiaoyuzhou/auth.js:249

        throw new CommandExecutionError(`Xiaoyuzhou API returned invalid JSON: ${getErrorMessage(error)}`);
    }
    const serviceCode = parsed?.code;
    if (serviceCode !== undefined && serviceCode !== null) {
        const numericCode = Number(serviceCode);
        if (!Number.isFinite(numericCode)) {
            throw new CommandExecutionError('Xiaoyuzhou API returned an invalid service code');
        }
        if (numericCode === 401 || numericCode === 403) {
            throw createXiaoyuzhouAuthError(`Xiaoyuzhou API rejected the credentials with service code ${numericCode}`);
        }
        if (numericCode !== 0 && numericCode !== 200) {
            throw new CommandExecutionError(
                parsed?.message || parsed?.msg || `Xiaoyuzhou API returned service code ${numericCode}`,
            );
        }
    }
    if (parsed?.success === false) {
        throw new CommandExecutionError(parsed?.message || parsed?.msg || 'Xiaoyuzhou API returned success=false');
    }
    return {
        credentials,
        raw: parsed,
        data: parsed?.data,
    };
}

export async function fetchXiaoyuzhouTranscriptBody(url, fetchImpl = fetch) {
    let response;
    try {
        response = await fetchImpl(url, {
            method: 'GET',
            headers: {
                'User-Agent': XIAOYUZHOU_DEFAULT_USER_AGENT,
                Accept: '*/*',
                Market: 'AppStore',
            },

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read parsed.message/msg in the error output — the API explains the soft failure (e.g. permission, content unavailable).
  2. Verify the account has access rights to the requested content (subscription/paywall status).
  3. Confirm the requested resource exists and parameters (IDs, ranges) are valid.
  4. If this endpoint legitimately uses success:false semantics, update the CLI to branch on it explicitly instead of treating it as generic failure.

Example fix

// before: throws with fallback text only
throw new CommandExecutionError(parsed?.message || parsed?.msg || 'Xiaoyuzhou API returned success=false');
// after: include the raw payload for diagnosis
throw new CommandExecutionError(`${parsed?.message || parsed?.msg || 'Xiaoyuzhou API returned success=false'}; payload=${JSON.stringify(parsed).slice(0, 300)}`);
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight: confirm account access tier covers the requested resource
const account = await getXiaoyuzhouAccountInfo(creds);
if (requiresSubscription(resource) && !account.isSubscribed) {
  throw new Error(`Resource ${resource.id} requires a subscription; account is free tier`);
}

Type guard

function isApiSuccessEnvelope(parsed) {
  return typeof parsed === 'object' && parsed !== null &&
    (parsed.success === undefined || parsed.success === true);
}

Try / catch

try {
  const result = await requestXiaoyuzhouJson(creds, path, params);
} catch (e) {
  if (e.message.includes('success=false')) {
    // soft business failure: surface parsed.message to the user, don't retry blindly
    console.error('API rejected request:', e.message);
  } else throw e;
}

Prevention

When it happens

Trigger: parsed.success is exactly false (strict ===) while code was absent or 0/200 — e.g. endpoints that return {success:false, message:'...'} envelopes for business-logic failures like paywalled content or incomplete data.

Common situations: Requesting premium/paywalled episode data with a free account; partial outages where the backend signals degraded success; endpoints that mix envelope styles (code-based vs success-based) and return success:false for soft failures.

Related errors


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