jackwener/OpenCLI · error · CommandExecutionError

kimi usage returned malformed payload: expected object

Error message

kimi usage returned malformed payload: expected object

What it means

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.

Source

Thrown at clis/kimi/usage.js:140

                const balanceMatch = text.match(/当前余额\\s*¥\\s*([\\d.]+)/);
                const spendMatch = text.match(/本月消费\\s*¥\\s*([\\d.]+)\\s*\\/\\s*(.+)/);
                result.balance = balanceMatch ? '¥' + balanceMatch[1] : null;
                result.monthlySpend = spendMatch ? '¥' + spendMatch[1] + ' / ' + spendMatch[2].trim() : null;
            }

            // Membership header
            const h1 = document.querySelector('h1');
            result.membershipName = h1 ? h1.textContent.trim() : null;

            const bodyText = document.body.innerText.trim().replace(/\\s+/g, ' ');
            const validMatch = bodyText.match(/有效期至:\\s*(\\d{4}-\\d{2}-\\d{2})/);
            result.membershipValidUntil = validMatch ? validMatch[1] : null;

            return result;
        })()`);

        if (!data || typeof data !== 'object' || Array.isArray(data)) {
            throw new CommandExecutionError('kimi usage returned malformed payload: expected object');
        }

        return [{
            membershipName: normalize(data.membershipName) || null,
            membershipValidUntil: data.membershipValidUntil || null,
            totalUsagePct: requireFinite(parsePct(data.totalUsagePct), 'totalUsagePct'),
            totalResetIn: requireText(data.totalResetIn, 'totalResetIn'),
            fiveHourUsagePct: requireFinite(parsePct(data.fiveHourUsagePct), 'fiveHourUsagePct'),
            fiveHourResetIn: requireText(data.fiveHourResetIn, 'fiveHourResetIn'),
            sevenDayUsagePct: requireFinite(parsePct(data.sevenDayUsagePct), 'sevenDayUsagePct'),
            sevenDayResetIn: requireText(data.sevenDayResetIn, 'sevenDayResetIn'),
            giftUsagePct: parsePct(data.giftUsagePct),
            giftValidUntil: normalize(data.giftValidUntil) || null,
            balance: normalize(data.balance) || null,
            monthlySpend: normalize(data.monthlySpend) || null,
        }];
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-authenticate / refresh the Kimi session token or cookies used by the usage snippet
  2. Run the embedded snippet manually and inspect its raw output to see why it is not an object
  3. Check whether Kimi changed the usage endpoint or response schema and update the parsing snippet
  4. Retry after verifying network connectivity to Kimi

Example fix

// before
const data = JSON.parse(execSync('node -e "...fetch usage..."').toString());
// after
let data;
try { data = JSON.parse(execSync('node -e "...fetch usage..."').toString()); } catch { data = null; }
if (data && typeof data === 'object' && !Array.isArray(data)) { /* proceed */ }
Defensive patterns

Strategy: validation

Validate before calling

function isPlainObject(v){ return v !== null && typeof v === 'object' && !Array.isArray(v); }
// call kimiUsage only after confirming session/token config exists

Type guard

const isUsagePayload = (d) => d !== null && typeof d === 'object' && !Array.isArray(d) && ('totalUsagePct' in d || 'membershipName' in d);

Try / catch

try {
  const [usage] = await opencli.kimi.usage();
} catch (e) {
  if (String(e.message).includes('malformed payload')) {
    // refresh auth or log raw output for inspection
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


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