jackwener/OpenCLI · error · CommandExecutionError
${failureMessage}: ${message}
Error message
${failureMessage}: ${message} What it means
When the underlying error message matches looksTikTokUpstreamFailure (API failed / HTTP <code> / invalid JSON / Failed to fetch / network), the mapper wraps it in CommandExecutionError as '<failureMessage>: <message>'.
Source
Thrown at clis/tiktok/utils.js:155
videoId: match[2],
};
}
export function looksTikTokAuthFailure(message) {
return /\bAUTH_REQUIRED\b|\b(auth|captcha|login|log in|permission|unauthori[sz]ed|forbidden)\b|HTTP\s+(401|403)\b/i.test(String(message || ''));
}
export function looksTikTokUpstreamFailure(message) {
return /\b(API failed|HTTP\s+\d+|invalid JSON|Failed to fetch|network|fetch)\b/i.test(String(message || ''));
}
export function throwTikTokPageContextError(error, { authMessage, emptyPattern, emptyTarget, failureMessage }) {
const message = getErrorMessage(error);
if (looksTikTokAuthFailure(message)) {
throw new AuthRequiredError('tiktok.com', authMessage);
}
if (looksTikTokUpstreamFailure(message)) {
throw new CommandExecutionError(`${failureMessage}: ${message}`);
}
if (emptyPattern.test(message)) {
throw new EmptyResultError(emptyTarget, message);
}
throw new CommandExecutionError(`${failureMessage}: ${message}`);
}
// Sentinels emitted by Route 1 (button-walker) IIFEs and mapped here to
// typed errors. Keeping the strings constant in one place makes the IIFE
// `throw new Error(...)` callsites greppable and the mapper exhaustive.
export const BUTTON_WALKER_SENTINELS = {
AUTH_REQUIRED: 'AUTH_REQUIRED',
BUTTON_NOT_FOUND: 'BUTTON_NOT_FOUND',
STATE_VERIFY_FAIL: 'STATE_VERIFY_FAIL',
RATE_LIMITED: 'RATE_LIMITED',
};
// Retryability for write-class typed errors. Captured in the hint stringView on GitHub (pinned to 49907e53dc)
Solutions
- Retry after a delay — upstream failures are often transient rate limits
- Inspect the embedded upstream message for the HTTP status and address it (429 => back off longer)
- Check network/proxy reachability of tiktok.com (curl -I https://www.tiktok.com)
- Update the CLI if invalid JSON persists — TikTok may have changed its response format
Example fix
// before
await cli.listLive();
// after
try { await cli.listLive(); }
catch (e) {
if (/rate|429/i.test(e.message)) await sleep(60_000);
await cli.listLive();
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-check connectivity
await fetch('https://www.tiktok.com', { method: 'HEAD' }); Type guard
const isUpstreamFailure = (e) => /\b(API failed|HTTP\s+\d+|invalid JSON|Failed to fetch|network|fetch)\b/i.test(e?.message ?? '');
Try / catch
try { return await cli.listExploreVideos(); } catch (e) { if (isUpstreamFailure(e) && attempts < 3) { await backoff(attempts); return retry(); } throw e; } Prevention
- Wrap listing calls in exponential-backoff retries
- Monitor for HTTP 429/5xx and lengthen backoff accordingly
- Pin/upgrade the CLI when 'invalid JSON' appears (API shape changed)
When it happens
Trigger: Any of the page-context listing commands hits an upstream fetch failure: TikTok API returned an HTTP error, response was invalid JSON, or the in-page fetch threw a network error.
Common situations: TikTok rate-limiting or 5xx responses; corporate proxy blocking tiktok.com; flaky network/DNS during scraping; TikTok changing an internal API response shape (invalid JSON).
Related errors
- 1point3acres request failed: ${error?.message || error}
- 1point3acres request failed: HTTP ${res.status} ${res.status
- Barchart greeks request failed: HTTP ${data.status}${data.st
- dianping could not resolve cityId for '${cityArg}' (pinyin=$
- Douyin search extraction failed: ${error instanceof Error ?
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/ff6d9cc34bd41960.
Report an issue: GitHub.