jackwener/OpenCLI · error · EmptyResultError
Topic ${id} does not contain a readable main post body.
Error message
Topic ${id} does not contain a readable main post body. What it means
The library renders the main post from its raw markdown; if raw is empty it falls back to converting the cooked HTML via htmlToMarkdown. If both yield an empty body, there is nothing readable to output, so an EmptyResultError is thrown.
Source
Thrown at clis/linux-do/topic-content.js:70
frontMatter ? `---\n${frontMatter}\n---` : '',
params.body.trim(),
].filter(Boolean).join('\n\n').trim();
}
function extractTopicContent(payload, id) {
const topic = normalizeTopicPayload(payload);
if (!topic) {
throw new CommandExecutionError('linux.do returned an unexpected topic payload');
}
const posts = topic.post_stream?.posts ?? [];
const mainPost = posts.find((post) => post.post_number === 1);
if (!mainPost) {
throw new EmptyResultError('linux-do/topic-content', `Could not find the main post for topic ${id}.`);
}
const body = typeof mainPost.raw === 'string' && mainPost.raw.trim()
? mainPost.raw.trim()
: htmlToMarkdown(mainPost.cooked ?? '');
if (!body) {
throw new EmptyResultError('linux-do/topic-content', `Topic ${id} does not contain a readable main post body.`);
}
return {
content: buildTopicMarkdownDocument({
title: topic.title?.trim() ?? '',
author: mainPost.username?.trim() ?? '',
likes: typeof mainPost.like_count === 'number' ? mainPost.like_count : undefined,
createdAt: toLocalTime(mainPost.created_at ?? ''),
url: `${LINUX_DO_HOME}/t/${id}`,
body,
}),
};
}
async function fetchTopicPayload(page, id) {
const result = await page.evaluate(`(async () => {
try {
const res = await fetch('/t/${id}.json?include_raw=true', { credentials: 'include' });
let data = null;
try {View on GitHub (pinned to 49907e53dc)
Solutions
- Sign in to linux.do in the browser session so full post bodies are served.
- Verify the post has visible content in the web UI.
- Check whether the post was hidden/deleted by moderators.
- Extend the pipeline to fall back to another field (e.g. cooked HTML as-is) if htmlToMarkdown output is empty.
Example fix
// before const body = typeof mainPost.raw === 'string' && mainPost.raw.trim() ? mainPost.raw.trim() : htmlToMarkdown(mainPost.cooked ?? ''); // after const body = (typeof mainPost.raw === 'string' && mainPost.raw.trim()) ? mainPost.raw.trim() : htmlToMarkdown(mainPost.cooked ?? '') || (mainPost.cooked ?? '').trim();
Defensive patterns
Strategy: fallback
Validate before calling
const raw = mainPost?.raw?.trim();
const cooked = mainPost?.cooked?.trim();
if (!raw && !cooked) throw new Error(`Topic ${id} has no readable body`); Type guard
const hasReadableBody = (post) => Boolean((typeof post?.raw === 'string' && post.raw.trim()) || (typeof post?.cooked === 'string' && post.cooked.trim()));
Try / catch
try {
return extractTopicContent(payload, id);
} catch (e) {
if (e instanceof EmptyResultError && /readable main post body/.test(e.message)) {
return { id, content: '' }; // degrade gracefully
} else throw e;
} Prevention
- Sign in so post bodies are not redacted
- Fall back to cooked HTML when raw is empty
- Skip hidden/deleted posts in batch jobs
When it happens
Trigger: Main post exists but has both empty raw and empty cooked fields — e.g. post content removed/hidden, content behind login not captured by the browser scrape, or a post consisting only of removed embeds.
Common situations: Moderator-hidden or deleted-post bodies; linux.do returning posts with redacted content to anonymous/crawler sessions; posts whose body is only an image that failed to render into markdown.
Related errors
- Could not find the main post for topic ${id}.
- No prices returned for train_no=${trainNo} ${fromStation.nam
- No 12306 stations match "${keyword}"
- No trains found from ${fromStation.name} to ${toStation.name
- 1point3acres thread
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/614f15ef93f389fb.
Report an issue: GitHub.