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
- Verify the note actually has images/video by opening it in a browser; if yes, the extractor selectors are stale — update buildDownloadExtractJs.
- Increase the wait before evaluate so lazy-loaded media is present in the DOM.
- Confirm the note ID/URL points to the intended note.
- 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
- Open the note in a browser to confirm it actually contains images/video before treating empty results as a bug.
- Add a longer settle wait so lazy-loaded media is in the DOM at evaluate time.
- Skip EmptyResultError notes gracefully in batch pipelines instead of failing the job.
- Update extractor media selectors if many known-media notes return empty.
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
- @${username} has no media
- Xiaohongshu media extraction returned malformed payload.
- No prices returned for train_no=${trainNo} ${fromStation.nam
- No 12306 stations match "${keyword}"
- No trains found from ${fromStation.name} to ${toStation.name
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/32899e8d63398de8.
Report an issue: GitHub.