jackwener/OpenCLI · error · CommandExecutionError

Pixiv user profile returned malformed novel ID: ${invalid}

Error message

Pixiv user profile returned malformed novel ID: ${invalid}

What it means

After requireProfileNovelIds obtains the novels map, every key must be a numeric string (Pixiv novel ID). If any key fails /^\d+$/, the library throws naming the invalid key, because non-numeric keys (e.g. 'meta', 'next', or error fields embedded in the map) cannot be novel IDs and would produce broken detail requests downstream.

Source

Thrown at clis/pixiv/novels.js:49

    novel_id: id,
    words: optionalCount(item.wordCount, 'word count'),
    characters: optionalCount(item.textCount ?? item.characterCount, 'character count'),
    bookmarks: optionalCount(item.bookmarkCount, 'bookmark count', 0),
    tags: tagsToString(item.tags),
    created: dateOnly(item.createDate),
    url: `https://www.pixiv.net/novel/show.php?id=${id}`,
  };
}

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',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log Object.keys(payload.novels) and inspect which key is non-numeric
  2. Filter out known non-numeric/metadata keys before passing the payload to the CLI
  3. Normalize keys by stripping non-digit prefixes (e.g. key.replace(/^\D+/, '')) if the API changed key format
  4. Refresh fixtures/cache with a fresh API response reflecting the current schema

Example fix

// before
const ids = requireProfileNovelIds(body);
// after
const cleaned = { ...body, novels: Object.fromEntries(
  Object.entries(body.novels).filter(([k]) => /^\d+$/.test(k))
)};
const ids = requireProfileNovelIds(cleaned);
Defensive patterns

Strategy: validation

Validate before calling

const ids = Object.keys(body?.novels ?? {});
const invalid = ids.filter(id => !/^\d+$/.test(id));
if (invalid.length) {
  console.warn('Ignoring non-numeric novel keys:', invalid);
}
const validIds = ids.filter(id => /^\d+$/.test(id));

Type guard

function isNumericIdKey(k) {
  return /^\d+$/.test(k);
}
function numericIdKeys(novels) {
  return Object.keys(novels).filter(isNumericIdKey);
}

Try / catch

try {
  ids = requireProfileNovelIds(body);
} catch (err) {
  const m = String(err.message).match(/malformed novel ID: (.+)$/);
  if (m) {
    console.warn(`Filtering out invalid novel key "${m[1]}"`);
    ids = Object.keys(body.novels).filter(k => /^\d+$/.test(k));
  } else throw err;
}

Prevention

When it happens

Trigger: The profile novels object contains non-ID keys — e.g. the API nests pagination/metadata fields alongside numeric IDs, keys arrive with quotes/whitespace/prefixes ('novel_123'), or a mocked/local fixture uses string slugs instead of numeric IDs.

Common situations: Pixiv API schema drift adding metadata keys to the novels map; hand-crafted test fixtures or cached snapshots with slug keys; a proxy rewriting keys; copying payload from docs with placeholder keys.

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