jackwener/OpenCLI · error · CommandExecutionError
${context} returned malformed browser output.
Error message
${context} returned malformed browser output. What it means
requireObjectEvaluateResult unwraps the result of an in-page browser evaluate call and asserts it is a plain (non-array) object. If the payload is null, an array, or a primitive, it throws CommandExecutionError with '<context> returned malformed browser output.' It is raised by state, waitForDiscordRoute and waitForDiscordContent when the route-state script returns an unexpected shape.
Source
Thrown at clis/discord-app/utils.js:21
const DISCORD_HOSTS = new Set(['discord.com', 'canary.discord.com', 'ptb.discord.com']);
const DISCORD_ORIGIN = 'https://discord.com';
const CHANNEL_ID_RE = /^\d{3,}$/;
function stringArg(value) {
return typeof value === 'string' && value.trim() ? value.trim() : '';
}
export function unwrapEvaluateResult(payload) {
if (payload && typeof payload === 'object' && !Array.isArray(payload) && 'session' in payload && 'data' in payload) {
return payload.data;
}
return payload;
}
function requireObjectEvaluateResult(payload, context) {
const value = unwrapEvaluateResult(payload);
if (!value || typeof value !== 'object' || Array.isArray(value)) {
throw new CommandExecutionError(`${context} returned malformed browser output.`);
}
return value;
}
function requireArrayEvaluateResult(payload, context) {
const value = unwrapEvaluateResult(payload);
if (!Array.isArray(value)) {
throw new CommandExecutionError(`${context} returned malformed browser output.`);
}
return value;
}
function requireNonEmptyRowField(row, field, context, index) {
if (!row || typeof row !== 'object' || Array.isArray(row)) {
throw new CommandExecutionError(`${context} returned malformed row ${index + 1}.`);
}
const value = String(row[field] || '').trim();
if (!value) {View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the command; transient navigation during polling often resolves it
- Inspect the automation driver's evaluate return handling to ensure plain objects are returned unserialized
- Confirm buildRouteStateScript still returns an object after any Discord UI/automation updates
- Wrap waitForDiscordRoute/waitForDiscordContent polling calls to tolerate and retry a malformed payload before failing
Example fix
// before
const state = await page.evaluate(buildRouteStateScript());
// after (tolerate transient malformed results)
let state = null;
for (let i = 0; i < 3 && !state; i++) {
try { state = requireObjectEvaluateResult(await page.evaluate(buildRouteStateScript()), 'state'); }
catch { await page.waitForTimeout(500); }
} Defensive patterns
Strategy: retry
Validate before calling
async function safeRouteState(page) {
const payload = await page.evaluate(buildRouteStateScript());
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) return null;
return payload;
} Type guard
function isRouteState(v) {
return v !== null && typeof v === 'object' && !Array.isArray(v);
} Try / catch
try {
await waitForDiscordRoute(page, target);
} catch (err) {
if (String(err.message).includes('malformed browser output')) {
await page.waitForTimeout(1000);
await waitForDiscordRoute(page, target); // transient navigation; retry once
} else throw err;
} Prevention
- Avoid triggering navigation/reloads while polling route state
- Keep the automated page on a discord.com origin during waits
- Confirm buildRouteStateScript still returns a plain object after updates
- Retry polling once on malformed output before failing
When it happens
Trigger: The in-page evaluate that reads Discord route state returns null/undefined (script threw inside the page), an array, or a string instead of an object — e.g. the page navigated mid-evaluate, the evaluation was serialized unexpectedly, or the route-state script was updated to return a non-object.
Common situations: Discord navigating/reloading while waitForDiscordRoute polls, causing the evaluate to resolve with null; a browser automation driver returning a wrapped or serialized payload the unwrapEvaluateResult doesn't recognize; a modified buildRouteStateScript accidentally returning a string.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Booking.com extractor returned an invalid status
- Ctrip cruise DOM extraction returned malformed rows
- discord-app channels
- Search input not found
- Discord search returned malformed browser payload.
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/ad6ff42bc532e8aa.
Report an issue: GitHub.