jackwener/OpenCLI · warning · EmptyResultError

No downloadable media found on this note.

Error message

No downloadable media found on this note.

What it means

EmptyResultError thrown when extraction succeeded (valid payload with a `media` array) but the array is empty — the note detail page contained no downloadable media. This typically means the note is media-less (text-only in a way the extractor doesn't capture), the media failed to load, or the extractor's media selectors missed the actual media elements.

Source

Thrown at clis/xiaohongshu/download.js:234

    ],
    columns: ['index', 'type', 'status', 'size'],
    func: async (page, kwargs) => {
        const rawInput = String(kwargs['note-id']);
        const output = kwargs.output;
        const noteId = parseNoteId(rawInput);
        await page.goto(buildNoteUrl(rawInput, { allowShortLink: true, commandName: 'xiaohongshu download' }));
        await page.wait({ time: 1 + Math.random() * 2 });
        const data = await page.evaluate(buildDownloadExtractJs(noteId));
        if (data?.securityBlock) {
            throw new CliError('SECURITY_BLOCK', 'Xiaohongshu security block: the note detail page was blocked by risk control.', /^https?:\/\//.test(rawInput)
                ? 'The page may be temporarily restricted. Try again later or from a different session.'
                : 'Try using a full URL from search results (with xsec_token) instead of a bare note ID.');
        }
        if (!data || typeof data !== 'object' || !Array.isArray(data.media)) {
            throw new CommandExecutionError('Xiaohongshu media extraction returned malformed payload.');
        }
        if (data.media.length === 0) {
            throw new EmptyResultError('xiaohongshu download', 'No downloadable media found on this note.');
        }
        // Extract cookies for authenticated downloads
        const cookies = formatCookieHeader(await page.getCookies({ domain: 'xiaohongshu.com' }));
        const resolvedNoteId = typeof data.noteId === 'string' && data.noteId.trim()
            ? data.noteId.trim()
            : noteId;
        return downloadMedia(data.media, {
            output,
            subdir: resolvedNoteId,
            cookies,
            filenamePrefix: resolvedNoteId,
            timeout: 60000,
        });
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the note actually has images/video by opening it in a browser; if yes, the extractor selectors are stale — update buildDownloadExtractJs.
  2. Increase the wait before evaluate so lazy-loaded media is present in the DOM.
  3. Confirm the note ID/URL points to the intended note.
  4. Handle EmptyResultError explicitly and skip such notes in batch jobs.

Example fix

// before
try { await downloadNote(url); } catch (e) { throw e; }
// after
try { await downloadNote(url); }
catch (e) {
  if (e.name === 'EmptyResultError') return skip(url); // no media on note
  throw e;
}
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the note actually has media before downloading (or treat empty as expected)
const noteMeta = await fetchNoteMeta(noteUrl); // page or API returning media count
if (!noteMeta || noteMeta.mediaCount === 0) {
  console.log('note has no media; skipping download');
}

Type guard

function hasDownloadableMedia(data) { return Array.isArray(data?.media) && data.media.length > 0; }

Try / catch

try {
  await cli.run('xiaohongshu download', { input: url });
} catch (err) {
  if (err instanceof EmptyResultError) return null; // legitimately no media
  throw err;
}

Prevention

When it happens

Trigger: Calling `xiaohongshu download` on a note whose page renders with zero detected media elements: a note type the extractor does not support, lazy-loaded media not yet in DOM at evaluate time, or extractor selectors missing media after a DOM change.

Common situations: Downloading a text-only or unsupported note type; scraping a note where images load lazily and evaluate ran too early; an extractor update lagging a Xiaohongshu DOM change.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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