jackwener/OpenCLI · error · CommandExecutionError
Douyin API request failed (${method} ${url}): ${error instan
Error message
Douyin API request failed (${method} ${url}): ${error instanceof Error ? error.message : String(error)} What it means
browserFetch executes a fetch inside the Douyin page context via page.evaluate and unwraps the result. If the evaluate call itself throws (page navigation, crash, CSP, script error), the error is wrapped in this CommandExecutionError including the method and URL. It signals the in-browser API request could not be completed at all.
Source
Thrown at clis/douyin/_shared/browser-fetch.js:51
if (!text.trim()) return res.ok ? null : { status_code: res.status, status_msg: 'Empty response body' };
try {
return JSON.parse(text);
} catch (error) {
return { status_code: res.ok ? -2 : res.status, status_msg: \`JSON parse failed: \${text.slice(0, 500) || String(error && error.message || error)}\` };
}
} catch (error) {
return { status_code: -1, status_msg: String(error && error.message || error) };
} finally {
clearTimeout(timer);
}
})()
`;
let result;
try {
result = unwrapEvaluateResult(await page.evaluate(js));
}
catch (error) {
throw new CommandExecutionError(`Douyin API request failed (${method} ${url}): ${error instanceof Error ? error.message : String(error)}`);
}
if (result == null) {
throw new CommandExecutionError(
`Empty response from Douyin API (${method} ${url})`,
'The endpoint may have been retired or may now require signed parameters.',
);
}
if (Array.isArray(result) || typeof result !== 'object') {
throw new CommandExecutionError(`Malformed response from Douyin API (${method} ${url})`);
}
if (result && typeof result === 'object' && 'status_code' in result) {
const code = result.status_code;
if (code !== 0) {
const msg = result.status_msg ?? result.message ?? 'unknown error';
if (isAuthLikeError(code, msg)) {
throw new AuthRequiredError('creator.douyin.com', `Douyin API auth/permission error ${code} at ${method} ${url}: ${msg}`);
}
throw new CommandExecutionError(`Douyin API error ${code} at ${method} ${url}: ${msg}`);View on GitHub (pinned to 49907e53dc)
Solutions
- Retry the request; transient navigation/network errors are common
- Ensure the browser stays on a douyin.com page for the request duration
- Refresh signatures/params and confirm the endpoint is still valid
- Update the library if Douyin changed its API/CSP
Example fix
// before
try { result = unwrapEvaluateResult(await page.evaluate(js)); }
catch (error) { throw new CommandExecutionError(`Douyin API request failed (${method} ${url}): ...`); }
// after
try { result = unwrapEvaluateResult(await page.evaluate(js)); }
catch (error) {
if (isTransient(error)) return browserFetch(page, method, url, opts); // retry once
throw new CommandExecutionError(`Douyin API request failed (${method} ${url}): ${error instanceof Error ? error.message : String(error)}`);
} Defensive patterns
Strategy: retry
Validate before calling
const onDouyin = await page.evaluate(() => location.hostname.includes('douyin.com'));
if (!onDouyin) throw new Error('browserFetch requires an active douyin.com page'); Type guard
function isFetchResult(r) { return r !== undefined && (r === null || typeof r === 'object' || typeof r === 'string'); } Try / catch
try {
const data = await browserFetch(page, 'GET', url);
} catch (e) {
if (/Douyin API request failed/.test(e.message)) {
await page.wait(2);
const data = await browserFetch(page, 'GET', url); // single retry
} else throw e;
} Prevention
- Keep the page stable (no navigation) during requests
- Check network health before batch API calls
- Regenerate signed params per request
- Update the library when Douyin changes its frontend
When it happens
Trigger: page.evaluate(js) throws — page navigated/closed mid-request, network error inside the page fetch rejected unhandled, evaluate serialization failure, or CSP blocking the injected script.
Common situations: Douyin SPA reloaded during the request; signed params stale after navigation; headless browser crashed; endpoint redirect triggering mixed-content/CSP failure.
Related errors
- coingecko coin request failed: ${error?.message || error}
- ${context}: malformed evaluate payload
- 申请抖音上传地址失败,非 JSON 响应: HTTP ${res.status} ${text.slice(0, 300
- 申请抖音上传地址失败: HTTP ${res.status} ${JSON.stringify(error ?? pay
- 提交抖音上传失败,非 JSON 响应: HTTP ${res.status} ${text.slice(0, 300)}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/f405d5f13891bef5.
Report an issue: GitHub.