jackwener/OpenCLI · error · CommandExecutionError
Pixiv novel returned malformed series title
Error message
Pixiv novel returned malformed series title
What it means
novelRowFromBody validates that a non-empty seriesTitle (from b.seriesTitle or seriesNavData.title) is a string. If it is a number, object, or array, the row builder refuses to emit a corrupted title column and throws CommandExecutionError.
Source
Thrown at clis/pixiv/novel.js:42
}
return { payload: body, identity: { novelId, title, userName, userId } };
}
export function novelRowFromBody(body, id) {
const normalized = requireNovelBody(body, id);
const b = normalized.payload;
const identity = normalized.identity;
if (b.seriesNavData != null && (Array.isArray(b.seriesNavData) || typeof b.seriesNavData !== 'object')) {
throw new CommandExecutionError('Pixiv novel returned malformed series metadata');
}
const series = b.seriesNavData || {};
const seriesId = b.seriesId ?? series.seriesId ?? '';
const seriesTitle = b.seriesTitle ?? series.title ?? '';
if (seriesId !== '' && !/^\d+$/.test(String(seriesId))) {
throw new CommandExecutionError('Pixiv novel returned malformed series ID');
}
if (seriesTitle !== '' && typeof seriesTitle !== 'string') {
throw new CommandExecutionError('Pixiv novel returned malformed series title');
}
const seriesOrder = series.order ?? b.seriesContentOrder ?? '';
if (seriesOrder !== '' && (!Number.isSafeInteger(seriesOrder) || seriesOrder < 1)) {
throw new CommandExecutionError('Pixiv novel returned malformed series order');
}
return {
novel_id: identity.novelId,
title: identity.title,
author: identity.userName,
user_id: identity.userId,
series_id: seriesId === '' ? '' : String(seriesId),
series_title: seriesTitle || '',
series_order: seriesOrder,
words: optionalCount(b.wordCount, 'word count'),
characters: optionalCount(b.characterCount ?? b.textCount, 'character count'),
bookmarks: optionalCount(b.bookmarkCount, 'bookmark count') || 0,
likes: optionalCount(b.likeCount, 'like count') || 0,
views: optionalCount(b.viewCount, 'view count') || 0,View on GitHub (pinned to 49907e53dc)
Solutions
- Dump the response to see the actual type of seriesNavData.title
- If title is a localized object, pick one locale (e.g. .title || .en || .ja) and pass a plain string as seriesTitle
- Update to the newest CLI version that may already unwrap localized titles
- Fix upstream normalization code so seriesTitle is always a string or ''
Example fix
// before
const row = novelRowFromBody(body, id); // title is {en: "...", ja: "..."}
// after
const t = body.seriesNavData?.title;
if (t && typeof t === 'object') body.seriesTitle = t.en ?? t.ja ?? '';
const row = novelRowFromBody(body, id); Defensive patterns
Strategy: type-guard
Validate before calling
const t = body?.seriesNavData?.title;
if (t != null && t !== '' && typeof t !== 'string') {
throw new Error('series title is not a string');
} Type guard
function isNonEmptyString(v) {
return typeof v === 'string' && v.length > 0;
} Try / catch
try {
const row = novelRowFromBody(body, id);
} catch (e) {
if (e.message.includes('malformed series title')) {
const t = body.seriesNavData?.title;
body.seriesTitle = typeof t === 'object' ? (t.en ?? t.ja ?? '') : '';
} else throw e;
} Prevention
- Unwrap localized title objects to a single string before building rows
- Type-check third-party/mirrored API responses at the boundary
- Avoid hand-built bodies with loosely typed title fields
When it happens
Trigger: seriesTitle resolves to a non-string non-empty value — e.g. seriesNavData.title is an object containing localized variants {en, ja}, or seriesTitle was set to a number in a crafted/cached body.
Common situations: Pixiv experiments with localized title objects; third-party API mirrors return title as {raw:...}; test fixtures typed incorrectly; a custom normalization step assigned the wrong field.
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
- Pixiv novel returned malformed series order
- ${label} must be an integer between ${min} and ${max}, got $
- Pixiv image download returned unexpected content type for ${
- Pixiv cookie lookup returned malformed entries: ${error?.mes
- Invalid bookmark type: ${type}. Expected "illust" or "novel"
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/3297500a91ad3b03.
Report an issue: GitHub.