jackwener/OpenCLI · error · CommandExecutionError
juejin recommend returned a malformed has_more flag
Error message
juejin recommend returned a malformed has_more flag
What it means
The recommend command validates that the has_more field in the Juejin API response, when present, is strictly a boolean. If the API returns has_more as a number, string, or other type, a CommandExecutionError is thrown because the CLI cannot reliably translate it into the ''/'true'/'false' string output format. This guards against silently misreporting pagination state.
Source
Thrown at clis/juejin/recommend.js:49
strategy: Strategy.PUBLIC,
browser: false,
args: [
{ name: 'limit', type: 'int', default: 20, help: 'Max articles (1-100, single page).' },
{ 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 it is a transient/proxied corruption, a fresh call may return the correct shape.
- Verify the current Juejin recommend API response schema; if has_more became an integer flag, update the validation to accept numbers 0/1.
- Pin or update the CLI to the version matching the live API shape.
- Log the raw payload to confirm the actual type of has_more before reporting an upstream bug.
Example fix
// before (boolean-only)
if (payload.has_more != null && typeof payload.has_more !== 'boolean') {
throw new CommandExecutionError('juejin recommend returned a malformed has_more flag');
}
// after (accept 0/1)
const hm = payload.has_more;
if (hm != null && typeof hm !== 'boolean' && hm !== 0 && hm !== 1) {
throw new CommandExecutionError('juejin recommend returned a malformed has_more flag');
} Defensive patterns
Strategy: type-guard
Validate before calling
if (payload.has_more !== undefined && payload.has_more !== null && typeof payload.has_more !== 'boolean') { throw new Error('unexpected has_more type: ' + typeof payload.has_more); } Type guard
function hasValidHasMore(p){ return p.has_more == null || typeof p.has_more === 'boolean'; } Try / catch
try {
return cliRecommend({ limit, cursor });
} catch (e) {
if (/malformed has_more/.test(e.message)) return { items: [], has_more: false, degraded: true };
throw e;
} Prevention
- Assert the API response shape once at the boundary (e.g. with zod: z.object({ has_more: z.boolean().optional(), cursor: z.unknown().optional() })).
- Re-record API fixtures after any Juejin API version change.
- Do not run responses through middlewares that coerce JSON booleans to strings/numbers.
When it happens
Trigger: Running the juejin recommend command when the response payload contains has_more with a non-boolean, non-null value (e.g. has_more: 1, has_more: "true", has_more: null is allowed but 0 or '1' is not).
Common situations: API version drift where Juejin starts returning has_more as 0/1 integers; a proxy or transformer middleware coercing booleans to strings; fixtures recorded from a different API version.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- juejin recommend returned a malformed cursor
- juejin recommend returned has_more without a next cursor
- ${label} must be a positive integer
- ${label} must be <= ${maxValue}
- coingecko top
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/af83b88225581424.
Report an issue: GitHub.