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

  1. Re-run the command; transient navigation during polling often resolves it
  2. Inspect the automation driver's evaluate return handling to ensure plain objects are returned unserialized
  3. Confirm buildRouteStateScript still returns an object after any Discord UI/automation updates
  4. 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

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

Related errors


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