jackwener/OpenCLI · error · CliError

FETCH_ERROR

FETCH_ERROR

Error message

No candidate endpoint returned JSON

What it means

fetchFirstJson tries each candidate API path in order and returns the first one that returns parseable JSON. If every candidate fails in a way that produced no failure record at all (lastFailure stays null, e.g. the loop body never produced a result), it throws CliError FETCH_ERROR 'No candidate endpoint returned JSON' with the checked endpoint list. It guards against silently returning nothing when all endpoint probes are inconclusive.

Source

Thrown at clis/zsxq/utils.js:129

          ok: false,
          url: path,
          error: error instanceof Error ? error.message : String(error),
        };
      }
    })()
  `);
}
export async function fetchFirstJson(page, paths) {
    let lastFailure = null;
    for (const path of paths) {
        const result = await browserJsonRequest(page, path);
        if (result.ok) {
            return result;
        }
        lastFailure = result;
    }
    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);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check network connectivity and that api.zsxq.com is reachable from the browser session
  2. Log in again (expired auth often causes HTML redirects instead of JSON)
  3. Inspect the 'Checked endpoints:' detail and test those URLs manually in the logged-in browser
  4. Update the CLI if ZSXQ changed its API endpoints
Defensive patterns

Strategy: retry

Try / catch

try {
  resp = await fetchFirstJson(page, paths);
} catch (e) {
  if (e.code === 'FETCH_ERROR' && /No candidate endpoint/.test(e.message)) {
    console.error('All endpoints unreachable:', e.detail);
  } else throw e;
}

Prevention

When it happens

Trigger: All candidate endpoints exhausted without any result object being recorded — e.g. paths array semantics changed, every probe aborted before producing lastFailure, or network layer returned non-JSON that was discarded without setting lastFailure.

Common situations: ZSXQ changed/removed legacy API paths so none of the candidates respond; a corporate proxy or offline network kills requests before a JSON parse; auth redirect returns HTML on every endpoint.

Related errors


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