jackwener/OpenCLI · error · CommandExecutionError
Zhihu answer comments referenced missing parent ${cursor}
Error message
Zhihu answer comments referenced missing parent ${cursor} What it means
resolveDepths walks each reply's parent chain up to the root comment to compute thread depth. If the chain reaches a comment id that is not present in childrenById (i.e. the parent was never fetched or was filtered out), the graph is incomplete, so it throws. This guards against producing rows with wrong or infinite depth values.
Source
Thrown at clis/zhihu/answer-comments-helpers.js:208
}
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);
if (!node) throw new CommandExecutionError(`Zhihu answer comments referenced missing parent ${cursor}`);
cursor = node.descriptor.parentId;
}
if (cursor !== rootId) depth = depths.get(cursor);
for (let index = chain.length - 1; index >= 0; index -= 1) depths.set(chain[index], ++depth);
}
return depths;
}
function toRow(comment, descriptor, ranks, context) {
return {
rank: ranks.rank,
comment_rank: ranks.commentRank,
reply_rank: ranks.replyRank,
depth: ranks.depth,
id: descriptor.id,
parent_id: descriptor.parentId,
author: memberName(comment.author) || 'anonymous',
reply_to: descriptor.parentId ? memberName(comment.reply_to_author) : '',
likes: normalizeCount(comment.like_count ?? comment.vote_count),View on GitHub (pinned to 49907e53dc)
Solutions
- Verify the reply chain: fetch with a larger --replies-limit so intermediate parents are included
- Skip (or attach to root) replies whose parent is missing instead of throwing — patch resolveDepths to treat unknown parents as depth 1
- Log cursor and the set of fetched ids to identify which parent id is absent, then check whether Zhihu's API omits deleted comments
- Retry later — if the parent is temporarily hidden it may reappear
Example fix
// before
const node = childrenById.get(cursor);
if (!node) throw new CommandExecutionError(`Zhihu answer comments referenced missing parent ${cursor}`);
// after
const node = childrenById.get(cursor);
if (!node) { depths.set(cursor, depth + 1); break; } // tolerate deleted/omitted parents Defensive patterns
Strategy: validation
Validate before calling
const fetchedIds = new Set(Object.keys(childrenById));
for (const node of childrenById.values()) {
if (node.descriptor.parentId !== rootId && !fetchedIds.has(node.descriptor.parentId)) {
console.warn('parent not fetched:', node.descriptor.parentId);
}
} Type guard
const hasParent = (node) => typeof node?.descriptor?.parentId === 'string' && (node.descriptor.parentId === rootId || childrenById.has(node.descriptor.parentId));
Try / catch
try { depths = resolveDepths(rootId, childrenById); }
catch (err) {
if (String(err.message).includes('referenced missing parent')) { /* rebuild rows skipping orphaned replies */ }
else throw err;
} Prevention
- Fetch enough replies per root that parent chains stay complete
- Log missing parent ids to detect API omissions (deleted comments)
- Treat orphaned replies as depth-1 children of the root in preprocessing
When it happens
Trigger: A reply's descriptor.parentId points to a comment that is not among the fetched replies for that root (parent deleted, hidden by Zhihu, or excluded by the --replies-limit/pagination cut).
Common situations: Zhihu deleted a mid-thread parent comment so children remain but the parent no longer appears in the API response; or replies were truncated by replies-limit while children of deeper nodes were still fetched; or the API returned comments out of order after an A/B change.
Related errors
- Zhihu answer comments reused id ${descriptor.id} across grap
- Zhihu answer comments contained a malformed ${role} row
- Zhihu answer comment ${id} had conflicting root provenance
- Zhihu answer comments returned conflicting data for comment
- Zhihu answer comments contained a reply cycle at ${cursor}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/18eed7c09da020e7.
Report an issue: GitHub.