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
- Refetch the root list and its replies together so counts and listings come from the same snapshot.
- Check whether the replies were deleted/hidden on zhihu.com for that root id.
- Verify the child-comment endpoint path in fetchChildComments still matches Zhihu's current API.
- 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
- Treat child_comment_count as a hint, not a guarantee — replies may be deleted at any time.
- Fetch root list and reply pages back-to-back to shrink the consistency window.
- Design output to tolerate missing reply subtrees.
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
- Zhihu answer comments contained a ${role} row without a stab
- Zhihu answer comment ${id} had conflicting root provenance
- Zhihu answer comment ${id} did not identify its immediate pa
- Zhihu answer comments returned conflicting data for comment
- Zhihu ${label} pagination returned a repeated next URL
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/00763ac86a4c9788.
Report an issue: GitHub.