jackwener/OpenCLI · error · EmptyResultError
Could not find the main post for topic ${id}.
Error message
Could not find the main post for topic ${id}. What it means
After normalizing the topic, extractTopicContent looks for the post with post_number === 1 (the main/OP post) in topic.post_stream.posts. If it is absent the command cannot render the document, so it throws an EmptyResultError naming the topic ID.
Source
Thrown at clis/linux-do/topic-content.js:64
const needsQuote = /[#{}[\],&*?|>!%@`'"]/.test(value) || /: /.test(value) || /:$/.test(value) || value.includes('\n');
frontMatterLines.push(`${key}: ${needsQuote ? `'${value.replace(/'/g, "''")}'` : value}`);
}
}
const frontMatter = frontMatterLines.join('\n');
return [
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,
}),
};
}View on GitHub (pinned to 49907e53dc)
Solutions
- Refetch the topic with the full post stream endpoint (`/t/<id>.json?print=true` or with post_ids for post 1).
- Verify the topic's first post still exists in the linux.do web UI.
- Retry with a signed-in session to get the complete stream.
- Fall back to rendering whatever posts are available instead of requiring post 1.
Example fix
// before
const payload = await fetchTopicPayload(page, id);
return [extractTopicContent(payload, id)];
// after
const payload = await fetchTopicPayload(page, id);
if (!payload?.post_stream?.posts?.some((p) => p.post_number === 1)) {
console.error(`Topic ${id} is missing its first post; skipping.`);
return [];
}
return [extractTopicContent(payload, id)]; Defensive patterns
Strategy: type-guard
Validate before calling
if (!payload?.post_stream?.posts?.some((p) => p.post_number === 1)) {
throw new Error(`Topic ${id} has no first post`);
} Type guard
const hasMainPost = (p) => Array.isArray(p?.post_stream?.posts) && p.post_stream.posts.some((x) => x.post_number === 1);
Try / catch
try {
return extractTopicContent(payload, id);
} catch (e) {
if (e instanceof EmptyResultError && /main post/.test(e.message)) {
console.error(`Skipping topic ${id}: first post missing.`);
return null;
} else throw e;
} Prevention
- Fetch the full post stream for each topic
- Skip topics whose OP was deleted
- Handle stream-chunked Discourse topics
When it happens
Trigger: A fetched topic whose post_stream.posts contains no post with post_number 1 — e.g. a truncated post stream from the API, a topic whose first post was deleted, or a partially fetched payload.
Common situations: Deleted first post by moderators; topics fetched with a chunked stream API where only later posts were loaded; sites returning summarized post lists; bot/anti-scrape responses missing the OP.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- linux.do returned an unexpected topic payload
- Topic ${id} does not contain a readable main post body.
- 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/80f3c6b441cc5beb.
Report an issue: GitHub.