jackwener/OpenCLI · error · CommandExecutionError

Bilibili conclusion API returned malformed model_result JSON

Error message

Bilibili conclusion API returned malformed model_result JSON

What it means

readModelResult parses the model_result field of Bilibili's video conclusion API response. When model_result arrives as a string (common, since the API returns it JSON-encoded), the function attempts JSON.parse; if parsing fails it throws this CommandExecutionError because the payload cannot be interpreted as the expected summary object.

Source

Thrown at clis/bilibili/summary.js:84

        }
        throw new CommandExecutionError(`Bilibili ${label} API failed: ${message} (${payload.code})`);
    }
    return payload.data;
}

function readModelResult(data, bvid) {
    if (!data || typeof data !== 'object' || Array.isArray(data)) {
        throw new CommandExecutionError('Bilibili conclusion API returned malformed data');
    }
    if (data.code !== 0) {
        throw new EmptyResultError('bilibili summary', `Bilibili has not generated an AI summary for ${bvid}.`);
    }
    let modelResult = data.model_result;
    if (typeof modelResult === 'string') {
        try {
            modelResult = JSON.parse(modelResult);
        } catch {
            throw new CommandExecutionError('Bilibili conclusion API returned malformed model_result JSON');
        }
    }
    if (!modelResult || typeof modelResult !== 'object' || Array.isArray(modelResult)) {
        throw new CommandExecutionError('Bilibili conclusion API returned malformed model_result');
    }
    const summary = String(modelResult.summary ?? '').trim();
    if (!summary) {
        throw new EmptyResultError('bilibili summary', `Bilibili has not generated an AI summary for ${bvid}.`);
    }
    const outline = modelResult.outline ?? [];
    if (!Array.isArray(outline)) {
        throw new CommandExecutionError('Bilibili conclusion API returned malformed outline');
    }
    return { summary, outline };
}

function rowsFromModel(model) {
    const rows = [{ time: '', content: model.summary }];

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the conclusion request in the logged-in browser session — malformed payloads are often transient or anti-bot artifacts.
  2. Log the raw model_result string before parsing to confirm what the API actually returned.
  3. Verify the request is made through a real page context (apiGet with page) with valid cookies rather than a bare HTTP client.
  4. Check that requireOkPayload succeeded and you are reading the right payload (view conclusion, not view details).
  5. Guard the parse yourself before calling, treating parse failure as 'summary unavailable' rather than a crash.

Example fix

// before
try {
    modelResult = JSON.parse(modelResult);
} catch {
    throw new CommandExecutionError('Bilibili conclusion API returned malformed model_result JSON');
}
// after
try {
    modelResult = JSON.parse(modelResult);
} catch (err) {
    console.error('model_result was:', data.model_result);
    return null; // treat as summary unavailable instead of throwing
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (typeof data.model_result === 'string' && data.model_result.trim()) {
    try { JSON.parse(data.model_result); } catch { console.warn('model_result is not valid JSON'); }
}

Type guard

function isParsableObject(v) {
  if (typeof v !== 'string') return v !== null && typeof v === 'object' && !Array.isArray(v);
  try { const p = JSON.parse(v); return p !== null && typeof p === 'object' && !Array.isArray(p); } catch { return false; }
}

Try / catch

try {
  const model = await readModelResult(page, bvid);
} catch (e) {
  if (String(e.message).includes('malformed model_result JSON')) {
    console.warn('Skipping video: malformed summary payload');
  } else throw e;
}

Prevention

When it happens

Trigger: The /x/web-interface/view/conclusion/get endpoint returned HTTP 200 with code 0, but its model_result field is a string that is not valid JSON — e.g. truncated response, HTML injected by an anti-bot page, or an empty/placeholder string.

Common situations: Bilibili A/B testing a new response shape; requests made without a proper browser session/cookies so the API returns a degraded or CAPTCHA-laced body; network proxies mangling the response body; videos for which the AI summary feature returns non-standard content.

Understand the failure class

Related errors


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