jackwener/OpenCLI · warning · CommandExecutionError

内容安全检测超时(30s),请稍后重试

Error message

内容安全检测超时(30s),请稍后重试

What it means

If the content-safety poll loop finishes without ever seeing a passing or rejected status (safetyPassed stays false) and the pre-check was reachable (so it isn't skipped as unavailable), the command gives up after ~30 seconds and throws this CommandExecutionError. It's a timeout of the moderation pre-check, not a rejection; a hint suggests --no_safety_check.

Source

Thrown at clis/douyin/publish.js:244

                    continue;
                }
                pollUnavailableCount = 0;
                const pollRes = poll.value;
                if (pollRes.status === 0 || (pollRes.has_done === true && pollRes.detect_result?.reason_code === 0 && (pollRes.detect_list?.length ?? 0) === 0)) {
                    safetyPassed = true;
                    break;
                }
                if (pollRes.status === 1) {
                    throw new CommandExecutionError('内容安全检测不通过,请修改后重试', '使用 --no_safety_check 跳过');
                }
                await sleep(2000);
            }
            if (!safetyPassed) {
                if (!preCheck.ok && pollUnavailableCount >= 3) {
                    process.stderr.write('  内容安全预检持续无响应,跳过本地预检,交由 create_v2 后的平台审核。\n');
                }
                else {
                    throw new CommandExecutionError('内容安全检测超时(30s),请稍后重试', '如确认要跳过本地预检,可使用 --no_safety_check;提交后仍会走抖音平台审核');
                }
            }
        }
        // ── Phase 8: create_v2 publish ──────────────────────────────────────
        const hashtagNames = extractHashtagNames(caption);
        const hashtags = [];
        let searchFrom = 0;
        for (const name of hashtagNames) {
            const idx = caption.indexOf(`#${name}`, searchFrom);
            if (idx === -1)
                continue;
            hashtags.push({ name, id: 0, start: idx, end: idx + name.length + 1 });
            searchFrom = idx + name.length + 1;
        }
        const publishText = caption ? `${title} ${caption}` : title;
        const captionOffset = caption ? title.length + 1 : 0;
        const textExtraArr = parseTextExtra(publishText, hashtags.map((hashtag) => ({
            ...hashtag,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the publish later when the safety service is less loaded
  2. Use --no_safety_check to skip the local pre-check and rely on post-submit platform review
  3. Check connectivity/latency to douyin.com from the automation environment
  4. Shorten the caption/title to reduce moderation processing time

Example fix

// before
await douyin.publish({ caption: caption, schedule: '2026-01-01 20:00' });
// after
await douyin.publish({ caption: caption, schedule: '2026-01-01 20:00', no_safety_check: true });
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check connectivity/latency before a scheduled publish
const t0 = Date.now();
await fetch('https://www.douyin.com', { method: 'HEAD' });
if (Date.now() - t0 > 5000) console.warn('Douyin is slow; safety pre-check may time out');

Try / catch

try {
  await douyin.publish({ title, caption });
} catch (e) {
  if (e instanceof CommandExecutionError && /内容安全检测超时/.test(e.message)) {
    await sleep(30000); // back off, then retry
    await douyin.publish({ title, caption });
  } else throw e;
}

Prevention

When it happens

Trigger: Polling loop exhausts its iterations (2s sleep per cycle up to 30s) with the poll endpoint responding but never returning status 0/1 — slow moderation service, pending state, or unexpected status codes.

Common situations: Douyin's safety service under heavy load or degraded; very long captions slowing moderation; network latency making each poll cycle take longer than expected; time-sensitive scheduled publishing retries during peak hours in Asia/Tokyo-China evening traffic.

Related errors


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