jackwener/OpenCLI · error · CommandExecutionError
juejin recommend returned has_more without a next cursor
Error message
juejin recommend returned has_more without a next cursor
What it means
When the Juejin recommend API says has_more is true (more pages exist) but provides no usable next cursor, the CLI throws a CommandExecutionError because continuing pagination would be impossible. This is an internal-consistency check on the API response: the two fields must agree.
Source
Thrown at clis/juejin/recommend.js:53
{ name: 'cursor', type: 'string', default: '0', help: 'Pagination cursor; pass back the previous response\'s next-page cursor to keep scrolling.' },
],
columns: ['rank', 'article_id', 'title', 'brief', 'views', 'likes', 'comments', 'author', 'tags', 'url', 'next_cursor', 'has_more'],
func: async (args) => {
const limit = requireBoundedInt(args.limit, 20, 100);
const cursor = requireCursor(args.cursor);
const payload = await juejinFetch(
'/recommend_api/v1/article/recommend_all_feed',
{ id_type: 2, client_type: 2608, sort_type: 200, limit, cursor },
'juejin recommend',
);
const data = readDataArray(payload, 'juejin recommend');
const nextCursor = readResponseCursor(payload.cursor);
if (payload.has_more != null && typeof payload.has_more !== 'boolean') {
throw new CommandExecutionError('juejin recommend returned a malformed has_more flag');
}
const hasMore = payload.has_more == null ? '' : String(payload.has_more);
if (payload.has_more === true && !nextCursor) {
throw new CommandExecutionError('juejin recommend returned has_more without a next cursor');
}
return data.slice(0, limit).map((row, i) => ({
...mapFeedItem(row, i + 1),
next_cursor: nextCursor,
has_more: hasMore,
}));
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Retry the request; if the API consistently omits the cursor, treat it as an upstream bug.
- Work around by keeping the last known cursor or by raising --limit so fewer pages are needed.
- Check whether the API changed pagination semantics and update the CLI accordingly.
- Report to the Juejin/CLI maintainers with the raw response payload.
Example fix
// before (hard failure on inconsistency)
if (payload.has_more === true && !nextCursor) {
throw new CommandExecutionError('juejin recommend returned has_more without a next cursor');
}
// after (degrade gracefully)
const hasMore = payload.has_more === true && nextCursor; Defensive patterns
Strategy: fallback
Validate before calling
if (payload.has_more === true && !(payload.cursor != null && payload.cursor !== '')) { /* inconsistent page — stop paginating */ } Type guard
function canContinue(p){ const c = p.cursor; return p.has_more === true && c != null && c !== ''; } Try / catch
try {
return cliRecommend({ limit, cursor });
} catch (e) {
if (/has_more without a next cursor/.test(e.message)) return { items: lastPage.items, has_more: false };
throw e;
} Prevention
- Treat (has_more && next_cursor) as the real loop condition, not has_more alone.
- Cap pagination iterations defensively to avoid infinite loops on buggy API states.
- Log the raw payload when this fires and report the upstream inconsistency to maintainers.
When it happens
Trigger: A recommend response where payload.has_more === true while payload.cursor is empty, null, undefined, or '' (readResponseCursor returns '' for those).
Common situations: Juejin backend bug where the final-but-nonempty page still sets has_more true without a cursor; hitting a rate-limited or degraded API variant that truncates fields; stale cached responses with missing cursor fields.
Related errors
- juejin recommend returned a malformed cursor
- juejin recommend returned a malformed has_more flag
- Xiaoyuzhou history returned an invalid loadMoreKey
- ${label} must be a positive integer
- ${label} must be <= ${maxValue}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9a8f2e870ff4bcee.
Report an issue: GitHub.