jackwener/OpenCLI · error · CommandExecutionError

${context} returned a malformed message.

Error message

${context} returned a malformed message.

What it means

requireReplyActionResult validates the object returned from page.evaluate() in the twitter reply flow before it is used. A browser-side result may include a `message` field for error reporting; the library throws this CommandExecutionError when `message` is present and non-null but is not a string (e.g. a number, object, or array). This protects callers from passing a non-string message into error construction or templating, which would produce broken diagnostics.

Source

Thrown at clis/twitter/reply.js:37

    // (silent: matched `/status/1234567` on substring `/status/123` and
    // accepted any host). parseTweetUrl bubbles ArgumentError on
    // malformed/off-domain inputs.
    const target = parseTweetUrl(rawUrl);
    return `https://x.com/compose/post?in_reply_to=${target.id}`;
}

function isPromiseCollectedError(err) {
    const msg = err instanceof Error ? err.message : String(err);
    return msg.includes('Promise was collected');
}

function requireReplyActionResult(value, context) {
    const result = unwrapBrowserResult(value);
    if (!result || typeof result !== 'object' || Array.isArray(result) || typeof result.ok !== 'boolean') {
        throw new CommandExecutionError(`${context} returned a malformed result.`);
    }
    if (Object.prototype.hasOwnProperty.call(result, 'message') && result.message != null && typeof result.message !== 'string') {
        throw new CommandExecutionError(`${context} returned a malformed message.`);
    }
    if (Object.prototype.hasOwnProperty.call(result, 'url') && result.url != null && typeof result.url !== 'string') {
        throw new CommandExecutionError(`${context} returned a malformed status url.`);
    }
    return result;
}

function validateReplyStatusUrl(result) {
    if (!result.url) return;
    let url;
    try {
        url = new URL(result.url);
    } catch {
        throw new CommandExecutionError('Twitter reply completion returned a malformed status url.');
    }
    const hostname = url.hostname.toLowerCase().replace(/^www\./, '');
    const match = url.pathname.match(/^\/([^/]+)\/status\/(\d+)\/?$/);
    if (!['x.com', 'twitter.com', 'mobile.twitter.com'].includes(hostname) || !match) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Fix the browser-side script to return a string: replace `return { ok: false, message: e }` with `return { ok: false, message: e instanceof Error ? e.message : String(e) }`.
  2. Check that the evaluate snippet's return object only puts strings into `message`; move structured error data to separate fields.
  3. If you control the caller, coerce before returning: `message: String(rawMessage)`.

Example fix

// before (inside page.evaluate)
catch (e) {
  return { ok: false, message: e };
}
// after
catch (e) {
  return { ok: false, message: e instanceof Error ? e.message : String(e) };
}
Defensive patterns

Strategy: type-guard

Validate before calling

// After receiving any browser result, before using .message:
if (result.message != null && typeof result.message !== 'string') {
  throw new Error('message field must be a string');
}

Type guard

function isReplyActionResult(v) {
  return !!v && typeof v === 'object' && !Array.isArray(v) &&
    typeof v.ok === 'boolean' &&
    (v.message == null || typeof v.message === 'string');
}

Try / catch

try {
  await cli('twitter', 'reply', { url, text });
} catch (e) {
  if (String(e.message).includes('returned a malformed message')) {
    // treat as a tooling/bridge bug: log the raw result and report
  } else throw e;
}

Prevention

When it happens

Trigger: The in-page script (reply click, reply text insertion, or submit polling) returns { ok, message: <non-string> } — e.g. `message: e` (an Error object) or `message: errorCode` (a number) instead of `message: e.toString()` / a string literal.

Common situations: Editing or writing a new page.evaluate() snippet inside clis/twitter/reply.js and forgetting to stringify the caught exception; a code change swapping a string message for a structured { code, text } object; serialization quirks where a string becomes a String wrapper object.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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