jackwener/OpenCLI · error · CommandExecutionError
Pixiv user novel item returned malformed ${label}
Error message
Pixiv user novel item returned malformed ${label} What it means
optionalCount validates that a numeric count field on a Pixiv user-novel item is a safe, non-negative integer before the CLI renders it. When the value is present but not a safe non-negative integer (e.g. a string, float, negative number, or boolean), the library throws CommandExecutionError to fail fast on malformed upstream Pixiv API payloads rather than emit corrupted ranking output. It only fires when the value is neither null nor empty string, since those fall back to the fallback value.
Source
Thrown at clis/pixiv/novels.js:16
import { cli, Strategy } from '@jackwener/opencli/registry';
import { ArgumentError, CommandExecutionError } from '@jackwener/opencli/errors';
import {
BATCH_SIZE,
normalizePixivPositiveInteger,
pixivFetch,
requirePixivId,
requirePixivPayloadObject,
requirePixivString,
} from './utils.js';
import { dateOnly, tagsToString } from './bookmark-utils.js';
function optionalCount(value, label, fallback = '') {
if (value == null || value === '') return fallback;
if (!Number.isSafeInteger(value) || value < 0) {
throw new CommandExecutionError(`Pixiv user novel item returned malformed ${label}`);
}
return value;
}
function userNovelRow(work, rank, expectedId) {
const item = requirePixivPayloadObject(work, 'Pixiv user novel item');
const id = requirePixivId(item.id, 'Pixiv user novel item');
if (id !== expectedId) {
throw new CommandExecutionError(`Pixiv user novels returned mismatched novel detail payload for ${expectedId}`);
}
const title = requirePixivString(item.title, 'Pixiv user novel item');
return {
rank,
title,
novel_id: id,
words: optionalCount(item.wordCount, 'word count'),
characters: optionalCount(item.textCount ?? item.characterCount, 'character count'),
bookmarks: optionalCount(item.bookmarkCount, 'bookmark count', 0),View on GitHub (pinned to 49907e53dc)
Solutions
- Log the raw payload item and the offending field to identify which count field has the wrong type
- Coerce the value before calling: Number.isFinite(+value) ? Number(value) : fallback, or pass value through a Number() cast if the API legitimately sends strings
- Upgrade/patch the CLI's optionalCount to accept numeric strings via /^\d+$/ before Number.isSafeInteger
- If Pixiv itself is returning malformed data, retry the request later or report the schema drift
Example fix
// before const words = optionalCount(item.total_words, 'total_words'); // after const rawWords = item.total_words; const words = optionalCount( typeof rawWords === 'string' && /^\d+$/.test(rawWords) ? Number(rawWords) : rawWords, 'total_words' );
Defensive patterns
Strategy: validation
Validate before calling
function isNonNegSafeInt(v) { return typeof v === 'number' && Number.isSafeInteger(v) && v >= 0; }
if (item.total_words != null && item.total_words !== '' && !isNonNegSafeInt(item.total_words)) {
throw new Error('Skipping novel: malformed total_words');
} Type guard
function isCount(v) {
return typeof v === 'number' && Number.isSafeInteger(v) && v >= 0;
}
function asCount(v, fallback = 0) {
if (typeof v === 'string' && /^\d+$/.test(v)) return Number(v);
return isCount(v) ? v : fallback;
} Try / catch
try {
row = userNovelRow(work, rank, expectedId);
} catch (err) {
if (String(err.message).includes('malformed')) {
console.warn(`Skipping rank ${rank}: ${err.message}`);
return null;
}
throw err;
} Prevention
- Coerce numeric API fields with Number() and validate before use
- Prefer explicit typeof checks over truthiness for numeric payload fields
- Wrap each row render so one malformed item does not abort the whole ranking run
- Pin and test against recorded Pixiv API fixtures to catch schema drift early
When it happens
Trigger: Pixiv's user novel detail endpoint returns a numeric field (like total_words, marker_count, or series count) as a string ('1234'), a float (12.5), a negative number, or another non-safe-integer type inside a works[] item passed to userNovelRow.
Common situations: Pixiv API schema changes or undocumented field types (numbers serialized as strings); proxies/caches re-serializing JSON with type coercion; a user-supplied expected id or scraped profile payload feeding the CLI with hand-edited data; new API fields no longer matching the CLI's assumptions.
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
- Invalid bookmark type: ${type}. Expected "illust" or "novel"
- Pixiv user novels returned mismatched novel detail payload f
- Pixiv user profile returned malformed novels payload
- Pixiv user profile returned malformed novel ID: ${invalid}
- Pixiv user novel details returned malformed works payload
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/37ab44d564d1741a.
Report an issue: GitHub.