{"record":{"id":"ca58194bcc8d9e61","repo":"jackwener/OpenCLI","slug":"kimi-usage-returned-malformed-payload-expected-ob","errorCode":null,"errorMessage":"kimi usage returned malformed payload: expected object","messagePattern":"kimi usage returned malformed payload: expected object","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/kimi/usage.js","lineNumber":140,"sourceCode":"                const balanceMatch = text.match(/当前余额\\\\s*¥\\\\s*([\\\\d.]+)/);\n                const spendMatch = text.match(/本月消费\\\\s*¥\\\\s*([\\\\d.]+)\\\\s*\\\\/\\\\s*(.+)/);\n                result.balance = balanceMatch ? '¥' + balanceMatch[1] : null;\n                result.monthlySpend = spendMatch ? '¥' + spendMatch[1] + ' / ' + spendMatch[2].trim() : null;\n            }\n\n            // Membership header\n            const h1 = document.querySelector('h1');\n            result.membershipName = h1 ? h1.textContent.trim() : null;\n\n            const bodyText = document.body.innerText.trim().replace(/\\\\s+/g, ' ');\n            const validMatch = bodyText.match(/有效期至：\\\\s*(\\\\d{4}-\\\\d{2}-\\\\d{2})/);\n            result.membershipValidUntil = validMatch ? validMatch[1] : null;\n\n            return result;\n        })()`);\n\n        if (!data || typeof data !== 'object' || Array.isArray(data)) {\n            throw new CommandExecutionError('kimi usage returned malformed payload: expected object');\n        }\n\n        return [{\n            membershipName: normalize(data.membershipName) || null,\n            membershipValidUntil: data.membershipValidUntil || null,\n            totalUsagePct: requireFinite(parsePct(data.totalUsagePct), 'totalUsagePct'),\n            totalResetIn: requireText(data.totalResetIn, 'totalResetIn'),\n            fiveHourUsagePct: requireFinite(parsePct(data.fiveHourUsagePct), 'fiveHourUsagePct'),\n            fiveHourResetIn: requireText(data.fiveHourResetIn, 'fiveHourResetIn'),\n            sevenDayUsagePct: requireFinite(parsePct(data.sevenDayUsagePct), 'sevenDayUsagePct'),\n            sevenDayResetIn: requireText(data.sevenDayResetIn, 'sevenDayResetIn'),\n            giftUsagePct: parsePct(data.giftUsagePct),\n            giftValidUntil: normalize(data.giftValidUntil) || null,\n            balance: normalize(data.balance) || null,\n            monthlySpend: normalize(data.monthlySpend) || null,\n        }];\n    },\n});","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/kimi/usage.js#L122-L158","documentation":"The kimi usage command shells out to an external script and expects it to yield a plain object with membership/usage fields. When the payload is missing, an array, or any other non-object, it throws CommandExecutionError('kimi usage returned malformed payload: expected object'). This guards downstream field access (normalize, parsePct) from operating on an unexpected shape.","triggerScenarios":"The inline `node -e`/eval snippet that computes `result` returns null/undefined (e.g. the embedded fetch failed and returned null), returns an array instead of an object, or the script output fails JSON/eval parsing so `data` is falsy.","commonSituations":"Kimi session token or cookies expired so the embedded request returns an error page or null; Kimi changed their usage API response shape; network outage inside the sub-command; stdout of the snippet polluted by warnings breaking parsing.","solutions":["Re-authenticate / refresh the Kimi session token or cookies used by the usage snippet","Run the embedded snippet manually and inspect its raw output to see why it is not an object","Check whether Kimi changed the usage endpoint or response schema and update the parsing snippet","Retry after verifying network connectivity to Kimi"],"exampleFix":"// before\nconst data = JSON.parse(execSync('node -e \"...fetch usage...\"').toString());\n// after\nlet data;\ntry { data = JSON.parse(execSync('node -e \"...fetch usage...\"').toString()); } catch { data = null; }\nif (data && typeof data === 'object' && !Array.isArray(data)) { /* proceed */ }","handlingStrategy":"validation","validationCode":"function isPlainObject(v){ return v !== null && typeof v === 'object' && !Array.isArray(v); }\n// call kimiUsage only after confirming session/token config exists","typeGuard":"const isUsagePayload = (d) => d !== null && typeof d === 'object' && !Array.isArray(d) && ('totalUsagePct' in d || 'membershipName' in d);","tryCatchPattern":"try {\n  const [usage] = await opencli.kimi.usage();\n} catch (e) {\n  if (String(e.message).includes('malformed payload')) {\n    // refresh auth or log raw output for inspection\n  } else throw e;\n}","preventionTips":["Keep the Kimi session token/cookies fresh","Log raw snippet output on failure to debug payload shape","Validate the response shape right after any Kimi API change","Wrap the embedded script with explicit JSON error output"],"tags":["cli","payload-validation","kimi","external-api"],"backgroundTag":"malformed-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}