jackwener/OpenCLI · error · CommandExecutionError
${label} request failed: ${err?.message ?? err}
Error message
${label} request failed: ${err?.message ?? err} What it means
juejinFetch wraps every outbound `fetch` to api.juejin.cn in a try/catch and rethrows any network-level failure (DNS, TCP, TLS, timeout, abort) as a CommandExecutionError. The original error's message is appended so the caller can see the underlying cause. It means the HTTP request never completed — the server response was never received.
Source
Thrown at clis/juejin/utils.js:99
/**
* POST JSON to a Juejin endpoint. The API returns `{ err_no, err_msg, data }`;
* a non-zero `err_no` is surfaced as a typed `CommandExecutionError`.
*/
export async function juejinFetch(path, body, label, method = 'POST') {
const url = `${JUEJIN_API_BASE}${path}`;
let resp;
try {
const init = {
method,
headers: { 'user-agent': UA, accept: 'application/json' },
};
if (method === 'POST') {
init.headers['content-type'] = 'application/json';
init.body = JSON.stringify(body ?? {});
}
resp = await fetch(url, init);
} catch (err) {
throw new CommandExecutionError(
`${label} request failed: ${err?.message ?? err}`,
'Check that api.juejin.cn is reachable from this network.',
);
}
if (resp.status === 429) {
throw new CommandExecutionError(
`${label} returned HTTP 429 (rate limited)`,
'Juejin throttles bursty traffic; wait a few seconds and retry.',
);
}
if (!resp.ok) {
throw new CommandExecutionError(`${label} returned HTTP ${resp.status}`);
}
let payload;
try {
payload = await resp.json();
} catch (err) {
throw new CommandExecutionError(`${label} returned malformed JSON: ${err?.message ?? err}`);View on GitHub (pinned to 49907e53dc)
Solutions
- Verify basic connectivity: `curl -I https://api.juejin.cn` — if this fails, fix DNS/proxy/firewall first.
- If behind a corporate proxy, set HTTPS_PROXY / HTTP_PROXY environment variables so Node's fetch can route through it.
- Check that the machine has working DNS (`nslookup api.juejin.cn`); add a resolver or hosts entry if needed.
- Retry later if the network to Chinese endpoints is degraded (e.g. use a VPN with China egress).
- Read the appended `err?.message` in the error text to identify the exact low-level cause (ENOTFOUND, ECONNREFUSED, ECONNRESET, CERT_...).
Example fix
// before (no connectivity config) $ opencli juejin recommend CommandExecutionError: juejin recommend request failed: getaddrinfo api.juejin.cn ENOTFOUND // after (export proxy / fix DNS first) $ export HTTPS_PROXY=http://corp-proxy:8080 $ opencli juejin recommend rank 1 ...
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight reachability check
async function juejinReachable() {
try {
const r = await fetch('https://api.juejin.cn', { method: 'HEAD', signal: AbortSignal.timeout(5000) });
return true; // any HTTP response means the host is reachable
} catch {
return false;
}
}
if (!(await juejinReachable())) throw new Error('api.juejin.cn unreachable; check network/proxy/DNS'); Type guard
function isFetchNetworkError(err) {
return err instanceof Error && (
err.cause != null ||
/ENOTFOUND|ECONNREFUSED|ECONNRESET|ETIMEDOUT|UND_ERR|CERT/.test(String(err.message))
);
} Try / catch
try {
const payload = await juejinFetch(path, body, label);
} catch (err) {
if (err instanceof CommandExecutionError && /request failed/.test(err.message)) {
console.error(`Network problem reaching Juejin: ${err.message}. Fix connectivity or set HTTPS_PROXY.`);
process.exitCode = 2; // transient/network class
return;
}
throw err;
} Prevention
- Run a one-time connectivity probe (HEAD request) before batch jobs and fail fast with a clear message.
- Configure HTTPS_PROXY/HTTP_PROXY explicitly in environments behind corporate proxies.
- Use AbortSignal.timeout on requests so hangs surface as timeouts instead of stalling scripts.
- Monitor DNS + TLS to api.juejin.cn from CI runners; use runners with egress to Chinese endpoints.
When it happens
Trigger: The `fetch(url, init)` call inside juejinFetch rejects: DNS resolution failure for api.juejin.cn, connection refused/timed out, TLS handshake failure, or the request was aborted. Any adapter command (recommend feed, hot list, etc.) that goes through juejinFetch can produce this.
Common situations: Running the CLI offline or on a network that blocks api.juejin.cn (common outside China, where Juejin may be slow or firewalled); corporate proxies intercepting TLS; IPv6/DNS misconfiguration; Node fetch agent issues; firewalls dropping the connection mid-request.
Related errors
- archive wayback request failed: ${error?.message || error}
- Failed to fetch Chess.com API ${url}: ${error?.message || er
- coingecko derivatives request failed: ${err?.message ?? err}
- coingecko trending request failed: ${error?.message || error
- `${label} request failed: ${err?.message ?? err}`
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/6aeb1e3acb066a6f.
Report an issue: GitHub.