jackwener/OpenCLI · error · CommandExecutionError

Douyin search parser found result cards without stable video

Error message

Douyin search parser found result cards without stable video url or description

What it means

CommandExecutionError thrown when projectSearchCards reports invalidCount > 0: Douyin rendered result cards, but at least one lacked a stable video URL or description, so the adapter refuses to emit partially-garbage rows. This protects downstream consumers of the tiktok-compatible row schema.

Source

Thrown at clis/douyin/search.js:301

                'www.douyin.com',
                'Douyin search results are blocked behind a login wall — log in at https://www.douyin.com in Chrome first.',
            );
        }
        if (result.state === 'empty') {
            throw new EmptyResultError('douyin search', `No Douyin videos matched "${keyword}".`);
        }
        if (result.state === 'timeout') {
            throw new CommandExecutionError('Douyin search did not render result cards within the timeout. Open the same search in Chrome and verify login/security state before retrying.');
        }
        if (!Array.isArray(result.cards)) {
            throw new CommandExecutionError('Douyin search: evaluator returned malformed cards payload');
        }
        if (result.cards.length === 0) {
            throw new EmptyResultError('douyin search', `No Douyin videos matched "${keyword}".`);
        }
        const projected = projectSearchCards(result.cards, limit);
        if (projected.invalidCount > 0) {
            throw new CommandExecutionError('Douyin search parser found result cards without stable video url or description');
        }
        if (projected.rows.length === 0) {
            throw new EmptyResultError('douyin search', `No Douyin videos matched "${keyword}".`);
        }
        return projected.rows;
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect the failing card HTML in the bound browser and update projectSearchCards' extraction hooks.
  2. Retry — if only ad cards appeared this run, a rerun may return all-valid cards.
  3. Relax the all-or-nothing policy locally by filtering invalid rows instead of throwing, if partial results are acceptable.

Example fix

// before
if (projected.invalidCount > 0) {
    throw new CommandExecutionError('Douyin search parser found result cards without stable video url or description');
}
// after (lenient variant)
if (projected.rows.length === 0) {
    throw new CommandExecutionError('Douyin search parser found no valid result cards');
}
Defensive patterns

Strategy: validation

Validate before calling

function cardLooksValid(card) {
  return typeof card?.url === 'string' && /\/video\/\d+/.test(card.url) && typeof card?.desc === 'string' && card.desc.length > 0;
}

Type guard

function isValidSearchRow(row) {
  return typeof row?.url === 'string' && row.url.startsWith('https://www.douyin.com/video/')
    && typeof row?.desc === 'string';
}

Try / catch

try {
  rows = await douyinSearch(keyword);
} catch (e) {
  if (/without stable video url or description/.test(e.message)) {
    console.error('Douyin markup drift or ad cards; inspect page HTML and update extractors');
  }
  throw e;
}

Prevention

When it happens

Trigger: Douyin markup change breaks the a[href*='/video/'] hook or the leaf-text shape heuristics; promoted/ad cards in the list have different structure; mixed content (live/hot cards) interleaved with video cards.

Common situations: After a Douyin front-end deploy; when search results include ads or recommended non-video cards; locale variations altering text shapes (万/亿 suffixes).

Related errors


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