jackwener/OpenCLI · error · CommandExecutionError
Bilibili creator comparison omitted metric ${definition.key}
Error message
Bilibili creator comparison omitted metric ${definition.key} What it means
metricValue checks that the metric key defined in the METRICS whitelist (e.g. `play`, `full_play_ratio`) actually exists on the source object (the row itself for target-sourced metrics like `duration`, otherwise `target.stat`). If the key is missing entirely, the library throws instead of silently emitting a wrong/empty value. null values are allowed and pass through, only total absence throws.
Source
Thrown at clis/bilibili/creator-stats.js:120
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;
}
function metricValue(target, definition) {
const source = definition.source === 'target' ? target : target.stat;
if (!Object.prototype.hasOwnProperty.call(source, definition.key)) {
throw new CommandExecutionError(`Bilibili creator comparison omitted metric ${definition.key}`);
}
const raw = source[definition.key];
if (raw === null) return null;
if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 0) {
throw new CommandExecutionError(`Bilibili creator comparison returned malformed metric ${definition.key}`);
}
if (definition.unit === 'percent' && raw > 10_000) {
throw new CommandExecutionError(`Bilibili creator comparison returned out-of-range percentage ${definition.key}`);
}
if ((definition.unit === 'count' || definition.unit === 'seconds') && !Number.isSafeInteger(raw)) {
throw new CommandExecutionError(`Bilibili creator comparison returned non-integer metric ${definition.key}`);
}
return definition.divisor ? raw / definition.divisor : raw;
}
cli({
site: 'bilibili',
name: 'creator-stats',View on GitHub (pinned to 49907e53dc)
Solutions
- Wait and retry — newly analyzed manuscripts often gain fields once analytics are computed.
- Verify the actual response body of the compare endpoint and update the METRICS key mapping in creator-stats.js if Bilibili renamed the field.
- Try a different, older manuscript to confirm the endpoint still returns all metrics.
- Update the CLI to a version whose METRICS whitelist matches the current Bilibili API.
Example fix
// before (throws on missing key) const v = metricValue(target, def); // after (caller tolerates omission) const source = def.source === 'target' ? target : target.stat; const v = Object.prototype.hasOwnProperty.call(source, def.key) ? metricValue(target, def) : null;
Defensive patterns
Strategy: validation
Validate before calling
const KEYS = ['play','like','comment','dm','fav','coin','share','total_new_attention_cnt','full_play_ratio','active_fans_rate','tm_rate','crash_rate','interact_rate','play_trans_fan_rate'];
const source = def.source === 'target' ? row : row.stat;
if (!KEYS.every((k) => Object.prototype.hasOwnProperty.call(source ?? {}, k))) { /* treat metrics as unavailable */ } Type guard
function hasMetric(source, key) {
return Boolean(source) && typeof source === 'object' && Object.prototype.hasOwnProperty.call(source, key);
} Try / catch
try {
const rows = await creatorStats(bvid);
} catch (e) {
if (/omitted metric/.test(e.message)) {
// degrade: render partial stats or nulls instead of aborting
} else throw e;
} Prevention
- Prefer newer manuscripts when sampling creator stats
- Pin the CLI to a version tested against the current Bilibili API
- Spot-check the raw compare endpoint after Bilibili creator-center updates
- Wrap batch jobs so one missing field doesn't abort the run
When it happens
Trigger: Bilibili's compare endpoint omits a whitelisted key from `target.stat` (or from the row for `durationSeconds`), e.g. after an API schema change or for archive types that don't carry certain counters.
Common situations: Undocumented API contract drift after Bilibili renames/removes fields; new archives where analytics fields haven't been populated yet; region-specific A/B rollouts of the creator center that drop fields.
Related errors
- Bilibili ${label} API returned malformed top_replies
- Bilibili comments reply ${index + 1} was missing rpid
- Bilibili comments reply ${index + 1} was missing ctime
- Bilibili creator comparison returned malformed stat data for
- Bilibili view API returned malformed paid-content metadata
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/16f4f8c950872c6f.
Report an issue: GitHub.