jackwener/OpenCLI · error · CommandExecutionError

当前浏览器适配器不支持文件注入

Error message

当前浏览器适配器不支持文件注入

What it means

The draft flow injects the video file directly into the page's <input type=file> via page.setFileInput. If the current browser adapter does not implement setFileInput, a CommandExecutionError is thrown telling the user to switch to Browser Bridge or another adapter that supports file injection.

Solutions

  1. Switch to the Browser Bridge adapter (or any mode supporting setFileInput) as the error message advises
  2. Upgrade the browser adapter/driver package to a version that implements setFileInput
  3. Check for the capability before running: `if (!page.setFileInput) { /* switch adapter */ }`

Example fix

// before
const page = await connect({ mode: 'cdp-attach' }); // no setFileInput
// after
const page = await connect({ mode: 'browser-bridge' }); // supports setFileInput
Defensive patterns

Strategy: fallback

Validate before calling

if (typeof page.setFileInput !== 'function') {
  console.error('Adapter lacks setFileInput — reconnect with Browser Bridge');
  process.exit(1);
}

Type guard

const supportsFileInput = (page) => typeof page?.setFileInput === 'function';

Try / catch

try {
  await cli.draft({ video, title });
} catch (e) {
  if (e instanceof CommandExecutionError && e.message.includes('不支持文件注入')) {
    const page = await connect({ mode: 'browser-bridge' });
    await cli.draft({ video, title }, { page });
  } else throw e;
}

Prevention

When it happens

Trigger: Running `douyin draft` while connected through a browser adapter lacking setFileInput — e.g. a remote/CDP-attached page object, a limited driver, or an adapter version predating the setFileInput API.

Common situations: Using a remote browser session/Bridge-less mode, older adapter versions, connecting to an already-running Chrome via plain CDP, or swapping the default browser backend in config.

Related errors


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

Appendix: source

Thrown at clis/douyin/draft.js:330

        if (!['.mp4', '.mov', '.avi', '.webm'].includes(ext)) {
            throw new ArgumentError(`不支持的视频格式: ${ext}(支持 mp4/mov/avi/webm)`);
        }
        const title = kwargs.title;
        if (title.length > 30) {
            throw new ArgumentError('标题不能超过 30 字');
        }
        const caption = kwargs.caption || '';
        if (caption.length > 1000) {
            throw new ArgumentError('正文不能超过 1000 字');
        }
        const coverPath = kwargs.cover;
        if (coverPath) {
            if (!fs.existsSync(path.resolve(coverPath))) {
                throw new ArgumentError(`封面文件不存在: ${path.resolve(coverPath)}`);
            }
        }
        if (!page.setFileInput) {
            throw new CommandExecutionError('当前浏览器适配器不支持文件注入', '请使用 Browser Bridge 或支持 setFileInput 的浏览器模式');
        }
        const visibilityLabel = VISIBILITY_LABELS[kwargs.visibility] ?? VISIBILITY_LABELS.public;
        await page.goto(DRAFT_UPLOAD_URL);
        await page.wait({ selector: 'input[type="file"]', timeout: 20 });
        await dismissKnownModals(page);
        await page.setFileInput([videoPath], 'input[type="file"]');
        await waitForDraftComposer(page);
        await dismissKnownModals(page);
        if (coverPath) {
            const coverSelector = await prepareCustomCoverInput(page);
            await page.setFileInput([path.resolve(coverPath)], coverSelector);
            await waitForCoverReady(page);
        }
        await fillDraftComposer(page, { title, caption, visibilityLabel });
        await page.wait({ time: 1 });
        const saveResult = await clickSaveDraft(page);
        const draftId = await waitForDraftResult(page, saveResult.creationId);
        return [

View on GitHub (pinned to 49907e53dc)