jackwener/OpenCLI · error · CommandExecutionError
Bilibili creator comparison returned a malformed manuscript
Error message
Bilibili creator comparison returned a malformed manuscript row
What it means
selectTarget iterates payload.data.list and whitelists each row: it must be a record with a string bvid matching /^BV[0-9A-Za-z]{10}$/. Because the endpoint is undocumented and unstable, any row failing that shape aborts the whole run with this CommandExecutionError instead of silently skipping bad rows. This is intentional strictness per the file's whitelist-based data contract.
Source
Thrown at clis/bilibili/creator-stats.js:97
) {
throw error;
}
const detail = `${error?.message ?? error} ${error?.hint ?? ''}`.trim();
if (/abort|timed?\s*out|timeout/i.test(detail)) {
throw new TimeoutError('Bilibili creator comparison', FETCH_TIMEOUT_SECONDS);
}
if (/HTTP\s+(401|403)|登录|passport|\/login\b/i.test(detail)) {
throw new AuthRequiredError('member.bilibili.com', `Bilibili creator-center login is required: ${detail}`);
}
throw new CommandExecutionError(`Bilibili creator comparison request failed: ${detail}`);
}
}
function selectTarget(list, bvid) {
const matches = [];
for (const item of list) {
if (!isRecord(item) || typeof item.bvid !== 'string' || !/^BV[0-9A-Za-z]{10}$/.test(item.bvid)) {
throw new CommandExecutionError('Bilibili creator comparison returned a malformed manuscript row');
}
if (item.bvid === bvid) matches.push(item);
}
if (matches.length > 1) {
throw new CommandExecutionError(`Bilibili creator comparison returned duplicate rows for ${bvid}`);
}
if (matches.length === 0) {
throw new EmptyResultError(
`bilibili creator-stats ${bvid}`,
'The manuscript was not present in the latest 100 creator analytics rows; it may be older, not owned by this account, or not analyzed yet.',
);
}
const target = matches[0];
if (!isRecord(target.stat)) {
throw new CommandExecutionError(`Bilibili creator comparison returned malformed stat data for ${bvid}`);
}
return target;
}View on GitHub (pinned to 49907e53dc)
Solutions
- Log the offending row (JSON.stringify the item) to see the new shape and update the whitelist validation
- Consider relaxing selectTarget to skip malformed rows instead of aborting, if Bilibili legitimately adds non-manuscript rows
- Update the bvid regex if Bilibili alters the BV ID format
- Refresh the sanitized probe fixtures and re-test against the live endpoint
Example fix
// before: abort on any bad row
if (!isRecord(item) || typeof item.bvid !== 'string' || !/^BV[0-9A-Za-z]{10}$/.test(item.bvid)) {
throw new CommandExecutionError('...malformed manuscript row');
}
// after: skip non-conforming rows
if (!isRecord(item) || typeof item.bvid !== 'string' || !/^BV[0-9A-Za-z]{10}$/.test(item.bvid)) {
continue;
} Defensive patterns
Strategy: validation
Validate before calling
function rowLooksValid(item) {
return item && typeof item === 'object' && !Array.isArray(item) && typeof item.bvid === 'string' && /^BV[0-9A-Za-z]{10}$/.test(item.bvid);
}
// fetch the list first and assert every row passes rowLooksValid before processing Type guard
function isManuscriptRow(item) {
return Boolean(item) && typeof item === 'object' && !Array.isArray(item) && typeof item.bvid === 'string' && /^BV[0-9A-Za-z]{10}$/.test(item.bvid);
} Try / catch
try {
const rows = await runCommand();
} catch (e) {
if (/malformed manuscript row/.test(e.message)) {
// log raw list JSON; either update the whitelist or relax to skip-and-continue
} else throw e;
} Prevention
- Keep the row whitelist in sync with observed live payloads (probe fixtures)
- Log the offending row JSON on failure to speed up schema-drift diagnosis
- Consider tolerating unknown extra row types instead of failing the entire run
- Track Bilibili changes to the undocumented compare endpoint
When it happens
Trigger: The compare endpoint's list contains an entry that is not an object, lacks bvid, or whose bvid is not a 12-char 'BV'+10 alphanumeric string (e.g. Bilibili adding ad/promoted rows, new row types, or a schema change).
Common situations: Bilibili injecting non-manuscript rows (ads, recommendations) into the analytics list; a schema change introducing new row shapes; fixtures drifting from production payloads.
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 creator comparison API returned malformed list data
- Bilibili creator comparison returned duplicate rows for ${bv
- Suno generation returned malformed clip identity.
- Bilibili creator comparison API returned a malformed envelop
- Bilibili conclusion API returned malformed data
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/c1b214cc4cf667b9.
Report an issue: GitHub.