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

  1. Refetch the topic with the full post stream endpoint (`/t/<id>.json?print=true` or with post_ids for post 1).
  2. Verify the topic's first post still exists in the linux.do web UI.
  3. Retry with a signed-in session to get the complete stream.
  4. 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

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


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