jackwener/OpenCLI · error · CommandExecutionError
Pixiv novel ${id} returned malformed detail payload
Error message
Pixiv novel ${id} returned malformed detail payload What it means
requireNovelDownloadBody checks the novel detail response before any files are written. If the body is null, an array, or not a plain object, it throws this error meaning the /ajax/novel/{id} endpoint did not return the expected detail object.
Source
Thrown at clis/pixiv/novel-download-utils.js:17
import * as fs from 'node:fs';
import * as path from 'node:path';
import { ArgumentError, CommandExecutionError } from '@jackwener/opencli/errors';
import { pixivFetch } from './utils.js';
import { dateOnly, tagsToString } from './bookmark-utils.js';
function optionalDownloadCount(value, label) {
if (value == null || value === '') return null;
if (!Number.isSafeInteger(value) || value < 0) {
throw new CommandExecutionError(`Pixiv novel ${label} returned malformed data`);
}
return value;
}
function requireNovelDownloadBody(body, id) {
if (!body || Array.isArray(body) || typeof body !== 'object') {
throw new CommandExecutionError(`Pixiv novel ${id} returned malformed detail payload`);
}
const novelId = String(body.id ?? '').trim();
const title = typeof body.title === 'string' ? body.title.trim() : '';
const author = typeof body.userName === 'string' ? body.userName.trim() : '';
const userId = String(body.userId ?? '').trim();
if (typeof body.content !== 'string') {
throw new CommandExecutionError(`Pixiv novel ${id} returned malformed content payload`);
}
if (!/^\d+$/.test(novelId) || novelId !== id || !title || !author || !/^\d+$/.test(userId)) {
throw new CommandExecutionError(`Pixiv novel ${id} returned malformed detail payload`);
}
// Validate metadata before any file is planned or created.
tagsToString(body.tags);
const createdDate = dateOnly(body.createDate);
const wordCount = optionalDownloadCount(body.wordCount, 'word count');
const bookmarkCount = optionalDownloadCount(body.bookmarkCount, 'bookmark count');
return {
...body,View on GitHub (pinned to 49907e53dc)
Solutions
- Verify the novel ID exists by opening it on pixiv in a browser
- Refresh pixiv cookies / re-authenticate the session
- Slow down bulk downloads to avoid throttling
- Log the raw response to identify whether pixiv changed the payload shape
Defensive patterns
Strategy: type-guard
Validate before calling
const body = await pixivFetch(page, `/ajax/novel/${id}`);
if (!body || Array.isArray(body) || typeof body !== 'object') {
throw new Error(`Novel ${id}: non-object detail payload`);
} Type guard
const isNovelDetail = (v) => !!v && !Array.isArray(v) && typeof v === 'object';
Try / catch
try {
await novelDownload(id);
} catch (e) {
if (/malformed detail payload/.test(e.message)) {
// refresh session, back off, or skip this ID
} else throw e;
} Prevention
- Keep session cookies valid
- Throttle bulk downloads
- Log raw responses to detect rate-limit/redirect payloads
- Verify the novel exists before scripting the download
When it happens
Trigger: pixivFetch returns null/falsey body, an array, or a non-object (error JSON, HTML parsed unexpectedly, or rate-limit page) for the novel detail endpoint.
Common situations: Novel deleted or ID wrong in a way that bypasses notFoundMsg; session expired causing a redirect payload; pixiv rate limiting during bulk novel downloads.
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
- Bilibili view API returned a malformed payload during paid-c
- Bilibili user search returned malformed mid for ${input}
- ${label} returned a malformed payload
- Sales Navigator messaging threads API returned malformed pay
- ${label} returned an unexpected response
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9fb64875c25f20bb.
Report an issue: GitHub.