jackwener/OpenCLI · error · CliError

${code}

${code}

Error message

${message}

What it means

When unwrapRespData sees payload.succeeded === false, it maps the API-level failure to a CliError whose code is the numeric record.code (as string) or the fallback 'API_ERROR', and whose message comes from record.info / record.error / a generic fallback. This converts ZSXQ's business-level errors (e.g. not-authed, not-found, rate-limit codes) into typed CLI errors.

Source

Thrown at clis/zsxq/utils.js:145

    }
    if (!lastFailure) {
        throw new CliError('FETCH_ERROR', 'No candidate endpoint returned JSON', `Checked endpoints: ${paths.join(', ')}`);
    }
    throw new CliError('FETCH_ERROR', lastFailure.error || 'Failed to fetch ZSXQ API', `Checked endpoints: ${paths.join(', ')}`);
}
export function unwrapRespData(payload) {
    const record = asRecord(payload);
    if (!record) {
        throw new CliError('PARSE_ERROR', 'Invalid ZSXQ API response');
    }
    if (record.succeeded === false) {
        const code = typeof record.code === 'number' ? String(record.code) : 'API_ERROR';
        const message = typeof record.info === 'string'
            ? record.info
            : typeof record.error === 'string'
                ? record.error
                : 'ZSXQ API returned an error';
        throw new CliError(code, message);
    }
    return (record.resp_data ?? record.data ?? payload);
}
export function getTopicsFromResponse(payload) {
    const data = unwrapRespData(payload);
    if (Array.isArray(data))
        return data;
    return pickArray(data.topics, data.list, data.records, data.items, data.search_result);
}
export function getCommentsFromResponse(payload) {
    const data = unwrapRespData(payload);
    if (Array.isArray(data))
        return data;
    return pickArray(data.comments, data.list, data.items);
}
export function getGroupsFromResponse(payload) {
    const data = unwrapRespData(payload);
    if (Array.isArray(data))

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Match on the error code: re-login in the browser for auth-related codes (e.g. 401/415)
  2. Verify the group_id/topic_id values you passed exist and are accessible
  3. Slow down request frequency if the code indicates rate limiting
  4. Catch CliError and branch on err.code to handle specific API codes programmatically

Example fix

// before
const data = await getData();
// after
try {
  const data = await getData();
} catch (e) {
  if (e.code === '401' || e.code === '415') await promptRelogin();
  else throw e;
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const data = await getData();
} catch (e) {
  if (e.code === '401' || e.code === '415') await reloginAndRetry();
  else if (e.code === 'API_ERROR') console.error('ZSXQ API error:', e.message);
  else throw e;
}

Prevention

When it happens

Trigger: Any API wrapper call (via data()) where ZSXQ responds succeeded:false — e.g. code 401/415 for expired auth (info about re-login), invalid group/topic ids, or permission errors; the thrown message/code are whatever the API returned.

Common situations: Expired session returning ZSXQ's auth error codes; requesting a private group you lack access to; deleted topic ids; ZSXQ rate-limit codes.

Related errors


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