jackwener/OpenCLI · error · CommandExecutionError

Zhihu answer root comment ${id} advertised replies but retur

Error message

Zhihu answer root comment ${id} advertised replies but returned none

What it means

When a root comment advertises child_comment_count > 0, fetchRepliesByRoot requires the child-comment endpoint to actually return at least one reply. Zero replies means the advertised replies are unreachable (deleted, permission-filtered, or endpoint drift), producing an incomplete tree, so the library throws.

Source

Thrown at clis/zhihu/answer-comments-helpers.js:189

        limit,
        label: 'answer child comments',
        role: 'child',
        expectedRootId: rootId,
        normalizeNext: (next) => normalizePageUrl(next, path, { limit: String(PAGE_SIZE), offset: null }),
    });
}
export async function fetchRepliesByRoot(page, roots, repliesLimit) {
    const repliesByRoot = new Map();
    if (repliesLimit === 0) return repliesByRoot;
    for (const root of roots) {
        const id = describeComment(root, 'root').id;
        if (!Number.isInteger(root.child_comment_count) || root.child_comment_count < 0) {
            throw new CommandExecutionError(`Zhihu answer root comment ${id} had malformed child count`);
        }
        if (root.child_comment_count === 0) continue;
        const children = await fetchChildComments(page, id, repliesLimit);
        if (children.length === 0) {
            throw new CommandExecutionError(`Zhihu answer root comment ${id} advertised replies but returned none`);
        }
        repliesByRoot.set(id, children);
    }
    return repliesByRoot;
}
function resolveDepths(rootId, childrenById) {
    const depths = new Map();
    for (const childId of childrenById.keys()) {
        if (depths.has(childId)) continue;
        const chain = [];
        const active = new Set();
        let cursor = childId;
        let depth = 0;
        while (cursor !== rootId && !depths.has(cursor)) {
            if (active.has(cursor)) throw new CommandExecutionError(`Zhihu answer comments contained a reply cycle at ${cursor}`);
            active.add(cursor);
            chain.push(cursor);
            const node = childrenById.get(cursor);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Refetch the root list and its replies together so counts and listings come from the same snapshot.
  2. Check whether the replies were deleted/hidden on zhihu.com for that root id.
  3. Verify the child-comment endpoint path in fetchChildComments still matches Zhihu's current API.
  4. If your policy tolerates vanished replies, relax this check to log-and-skip instead of throw.

Example fix

// before
if (children.length === 0) throw new CommandExecutionError(`... advertised replies but returned none`);
// after: tolerate vanished replies
if (children.length === 0) continue; // replies were removed server-side
Defensive patterns

Strategy: try-catch

Validate before calling

// skip roots whose advertised replies cannot be fetched, instead of failing the batch
async function safeReplies(page, roots, limit) {
  const map = new Map();
  for (const root of roots) {
    try {
      const kids = await fetchChildComments(page, String(root.id), limit);
      if (kids.length > 0) map.set(String(root.id), kids);
    } catch { /* root advertised replies that are gone; skip */ }
  }
  return map;
}

Try / catch

try {
  const byRoot = await fetchRepliesByRoot(page, roots, repliesLimit);
} catch (err) {
  if (String(err.message).includes('advertised replies but returned none')) {
    console.warn('Replies vanished between count and fetch; continuing with roots only');
    return fetchRootComments(page, answerId, order, limit);
  }
  throw err;
}

Prevention

When it happens

Trigger: root.child_comment_count >= 1 but fetchChildComments(page, id, repliesLimit) returns an empty array — the reply listing for that root yielded no rows.

Common situations: All replies to a root were deleted moments after the root's count was cached; Zhihu filtering replies (deleted authors, censored content) that still count toward child_comment_count; or a wrong repliesLimit of 0 interacting with stale counts. Also hit when the reply endpoint URL changed.

Related errors


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