jackwener/OpenCLI · error · CommandExecutionError

Pixiv user novel details returned malformed works payload

Error message

Pixiv user novel details returned malformed works payload

What it means

requireDetailWorks validates the 'Pixiv user novel details' response: works must be a non-null, non-array object (map). Missing/null works, an array, or a primitive triggers this throw because the detail step cannot proceed without a works map to iterate for userNovelRow. It's a structural gate protecting the CLI from upstream payload shape drift or failed requests parsed as success.

Source

Thrown at clis/pixiv/novels.js:57

}

function requireProfileNovelIds(body) {
  const payload = requirePixivPayloadObject(body, 'Pixiv user profile');
  if (!payload.novels || Array.isArray(payload.novels) || typeof payload.novels !== 'object') {
    throw new CommandExecutionError('Pixiv user profile returned malformed novels payload');
  }
  const ids = Object.keys(payload.novels);
  const invalid = ids.find(id => !/^\d+$/.test(id));
  if (invalid) {
    throw new CommandExecutionError(`Pixiv user profile returned malformed novel ID: ${invalid}`);
  }
  return ids;
}

function requireDetailWorks(body) {
  const payload = requirePixivPayloadObject(body, 'Pixiv user novel details');
  if (!payload.works || Array.isArray(payload.works) || typeof payload.works !== 'object') {
    throw new CommandExecutionError('Pixiv user novel details returned malformed works payload');
  }
  return payload.works;
}

cli({
  site: 'pixiv',
  name: 'novels',
  access: 'read',
  description: "List a Pixiv user's novels",
  domain: 'www.pixiv.net',
  strategy: Strategy.COOKIE,
  args: [
    { name: 'user-id', positional: true, required: true, help: 'Pixiv user ID' },
    { name: 'limit', type: 'int', default: 20, help: 'Number of results' },
  ],
  columns: ['rank', 'title', 'novel_id', 'words', 'characters', 'bookmarks', 'tags', 'created', 'url'],
  func: async (page, kwargs) => {
    const userId = String(kwargs['user-id'] ?? '').trim();

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect the raw HTTP response body and status code to distinguish auth/rate-limit failures from shape drift
  2. Re-authenticate or refresh Pixiv session cookies if the body indicates login required
  3. Handle the empty case: treat missing/array-shaped works as 'no details' and skip instead of throwing
  4. Retry with backoff if the response was truncated or rate-limited
  5. Patch requireDetailWorks to normalize arrays to maps keyed by work id

Example fix

// before
const works = requireDetailWorks(body);
// after
if (body && Array.isArray(body.works)) {
  body.works = Object.fromEntries(body.works.map(w => [String(w.id), w]));
}
const works = requireDetailWorks(body);
Defensive patterns

Strategy: try-catch

Validate before calling

function hasValidWorksMap(body) {
  return body != null &&
    typeof body.works === 'object' && body.works !== null &&
    !Array.isArray(body.works);
}
if (!hasValidWorksMap(body)) throw new Error('Novel details response unusable: works is not an object map');

Type guard

function hasWorksMap(p) {
  return typeof p === 'object' && p !== null &&
    typeof p.works === 'object' && p.works !== null && !Array.isArray(p.works);
}

Try / catch

try {
  works = requireDetailWorks(body);
} catch (err) {
  if (String(err.message).includes('malformed works payload')) {
    console.warn('No works map in details response; skipping this batch');
    works = {};
  } else throw err;
}

Prevention

When it happens

Trigger: The user-novel detail endpoint returns {works: null}, {works: []}, {works: '...'}, or omits works — typically when the request failed silently, the novels in the profile had no accessible details, or the API response schema changed.

Common situations: Expired Pixiv session/cookies yielding an error body; rate limiting returning partial JSON; users whose novels are all private so details come back empty/array-shaped; library version vs current Pixiv API mismatch.

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/e147f029e5b7236d. Report an issue: GitHub.