{"record":{"id":"48a3f093def72712","repo":"jackwener/OpenCLI","slug":"bilibili-conclusion-api-returned-malformed-data","errorCode":null,"errorMessage":"Bilibili conclusion API returned malformed data","messagePattern":"Bilibili conclusion API returned malformed data","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/bilibili/summary.js","lineNumber":74,"sourceCode":"}\n\nfunction requireOkPayload(payload, label) {\n    if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n        throw new CommandExecutionError(`Bilibili ${label} API returned a malformed payload`);\n    }\n    if (payload.code !== 0) {\n        const message = payload.message ?? 'unknown error';\n        if (payload.code === -101 || payload.code === -403 || /登录|权限|forbidden|permission|login/i.test(String(message))) {\n            throw new AuthRequiredError('bilibili.com', `Bilibili ${label} API requires login or permission: ${message} (${payload.code})`);\n        }\n        throw new CommandExecutionError(`Bilibili ${label} API failed: ${message} (${payload.code})`);\n    }\n    return payload.data;\n}\n\nfunction readModelResult(data, bvid) {\n    if (!data || typeof data !== 'object' || Array.isArray(data)) {\n        throw new CommandExecutionError('Bilibili conclusion API returned malformed data');\n    }\n    if (data.code !== 0) {\n        throw new EmptyResultError('bilibili summary', `Bilibili has not generated an AI summary for ${bvid}.`);\n    }\n    let modelResult = data.model_result;\n    if (typeof modelResult === 'string') {\n        try {\n            modelResult = JSON.parse(modelResult);\n        } catch {\n            throw new CommandExecutionError('Bilibili conclusion API returned malformed model_result JSON');\n        }\n    }\n    if (!modelResult || typeof modelResult !== 'object' || Array.isArray(modelResult)) {\n        throw new CommandExecutionError('Bilibili conclusion API returned malformed model_result');\n    }\n    const summary = String(modelResult.summary ?? '').trim();\n    if (!summary) {\n        throw new EmptyResultError('bilibili summary', `Bilibili has not generated an AI summary for ${bvid}.`);","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/bilibili/summary.js#L56-L92","documentation":"readModelResult() inspects the `data` object returned by the conclusion endpoint (already unwrapped by requireOkPayload). If data is missing or not a plain object, it throws this CommandExecutionError: the endpoint answered successfully at the envelope level but the nested data needed to find the AI summary is absent or the wrong shape, so parsing cannot continue.","triggerScenarios":"The conclusion API returns `{ code: 0 }` with no `data` field (observed on videos with no AI summary in some API states), or data is a string/array/null due to an API format change; readModelResult is called by command() after conclusionData().","commonSituations":"Bilibili silently changed the response contract for videos lacking summaries; a proxy/cache stripped the data field; older CLI version parsing a newer/older API shape.","solutions":["Retry with a different video to confirm whether the endpoint ever returns data for your session.","Log the raw conclusion response to inspect what shape data actually has.","Update/patch the CLI's response parsing if Bilibili changed the contract.","Treat it like the missing-summary case: verify in a browser whether the video has an AI summary at all."],"exampleFix":"// before\nconst model = readModelResult(payload.data, bvid); // data may be undefined\n// after\nif (!payload.data || typeof payload.data !== 'object') {\n  throw new Error(`conclusion data missing: ${JSON.stringify(payload).slice(0, 200)}`);\n}\nconst model = readModelResult(payload.data, bvid);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function hasConclusionData(payload) {\n  const d = payload?.data;\n  return d !== null && typeof d === 'object' && !Array.isArray(d);\n}","tryCatchPattern":"try {\n  const model = await summaryCommand(bvid);\n} catch (e) {\n  if (/conclusion API returned malformed data/.test(e.message)) {\n    // endpoint returned code:0 with no data — likely no summary support for this video\n    return null;\n  }\n  throw e;\n}","preventionTips":["Guard payload.data before parsing model_result.","Compare raw responses across videos to detect API contract changes early.","Keep the CLI/parsing code in sync with current Bilibili response shapes.","Bypass proxies/caches when debugging to rule out stripped fields."],"tags":["api-response","schema-validation","bilibili"],"backgroundTag":"malformed-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}