jackwener/OpenCLI · error · CommandExecutionError

Pixiv illustration ${id} returned malformed detail payload

Error message

Pixiv illustration ${id} returned malformed detail payload

What it means

requireIllustBody first checks the structural shape of the response from /ajax/illust/<id>: it must be a non-null, non-array object. If Pixiv returned null, an array, a string, or nothing at all (e.g. an error envelope or login page parsed to a non-object), this CommandExecutionError is thrown — this is the shape-check branch, distinct from the later content-check (error 3158).

Source

Thrown at clis/pixiv/detail.js:7

import { cli, Strategy } from '@jackwener/opencli/registry';
import { ArgumentError, CommandExecutionError } from '@jackwener/opencli/errors';
import { pixivFetch } from './utils.js';

function requireIllustBody(body, id) {
    if (!body || Array.isArray(body) || typeof body !== 'object') {
        throw new CommandExecutionError(`Pixiv illustration ${id} returned malformed detail payload`);
    }
    const illustId = String(body.illustId ?? '').trim();
    const title = String(body.illustTitle ?? '').trim();
    const userName = String(body.userName ?? '').trim();
    const userId = String(body.userId ?? '').trim();
    if (!/^\d+$/.test(illustId) || illustId !== id || !title || !userName || !/^\d+$/.test(userId)) {
        throw new CommandExecutionError(`Pixiv illustration ${id} returned malformed detail payload`);
    }
    return { ...body, illustId, illustTitle: title, userName, userId };
}

cli({
    site: 'pixiv',
    name: 'detail',
    access: 'read',
    description: 'View illustration details (tags, stats, URLs)',
    domain: 'www.pixiv.net',
    strategy: Strategy.COOKIE,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the illustration ID exists and is publicly viewable in a logged-in browser; use a different ID to confirm.
  2. Re-authenticate the Pixiv session on `page` — expired logins commonly produce non-detail payloads.
  3. Log/inspect the raw pixivFetch body when this fires to see whether it's an error envelope, HTML, or null.
  4. Ensure pixivFetch's notFoundMsg/error handling covers the response before requireIllustBody runs.
  5. Retry with backoff if Cloudflare/rate limiting is suspected; otherwise treat the artwork as unavailable.

Example fix

// before
const body = await pixivFetch(page, `/ajax/illust/${id}`, { notFoundMsg: `Illustration not found: ${id}` });
const b = requireIllustBody(body, id);
// after
let body = await pixivFetch(page, `/ajax/illust/${id}`, { notFoundMsg: `Illustration not found: ${id}` });
if (body && typeof body === 'object' && body.error) {
  throw new CommandExecutionError(`Pixiv illustration ${id} unavailable: ${body.message ?? 'unknown error'}`);
}
const b = requireIllustBody(body, id);
Defensive patterns

Strategy: try-catch

Validate before calling

function looksLikeIllustDetail(body) {
  return body !== null && typeof body === 'object' && !Array.isArray(body);
}
if (!looksLikeIllustDetail(body)) {
  console.warn('illust detail call returned non-object; session or artwork likely unavailable');
}

Type guard

function isIllustDetailObject(body) {
  return typeof body === 'object' && body !== null && !Array.isArray(body);
}

Try / catch

let b;
try {
  b = requireIllustBody(body, id);
} catch (e) {
  if (e.message.includes('malformed detail payload')) {
    console.error(`Illust ${id} unavailable: got ${Array.isArray(body) ? 'array' : typeof body}; check login or artwork existence`);
    return []; // skip gracefully
  }
  throw e;
}

Prevention

When it happens

Trigger: The /ajax/illust/<id> call resolves with body === null/undefined, a JSON array, or a string — e.g. Pixiv returned {"error":true} handled upstream to null, a deleted/restricted illustration returning an empty body, or a proxy/captcha HTML page.

Common situations: Illustration deleted or made private so the ajax endpoint returns an error object instead of detail data; session expired and Pixiv serves HTML/JSON that isn't the detail object; corporate proxy or Cloudflare challenge intercepting the request; rate limiting returning a non-standard envelope.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/3623d84b2b72ddbb. Report an issue: GitHub.