jackwener/OpenCLI · error · CommandExecutionError

${context} returned a malformed status url.

Error message

${context} returned a malformed status url.

What it means

requireReplyActionResult additionally validates the `url` field of the browser-evaluate result for the reply flow. If the in-page script reports a status URL (`url`) that is present and non-null but not a string, the library throws this CommandExecutionError instead of letting a non-string propagate into URL parsing. It is a defensive contract check on the browser bridge data.

Source

Thrown at clis/twitter/reply.js:40

    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) {
        throw new CommandExecutionError('Twitter reply completion returned a malformed status url.');
    }
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Return a string from the page script: `url: location.href` or `url: anchor.href` rather than the object.
  2. Coerce before returning: `url: String(rawUrl)`.
  3. Verify the evaluate snippet only sets `url` when it has a string permalink matching /status/<id>.

Example fix

// before
return { ok: true, url: new URL(permalink) };
// after
return { ok: true, url: permalink.href };
Defensive patterns

Strategy: type-guard

Validate before calling

if (result.url != null && typeof result.url !== 'string') {
  throw new Error('url field must be a string');
}

Type guard

function hasStringUrl(v) {
  return v == null || typeof v !== 'object' || v.url == null || typeof v.url === 'string';
}

Try / catch

try {
  await cli('twitter', 'reply', { url, text });
} catch (e) {
  if (String(e.message).includes('malformed status url') && !(e instanceof TypeError) === false || String(e.message).includes('returned a malformed status url')) {
    // non-string url from bridge: log raw result, do not retry blindly
  } else throw e;
}

Prevention

When it happens

Trigger: A page.evaluate() snippet in the reply flow returns { ok: true, url: <non-string> } — e.g. `url: location` (a Location object), `url: tweetId` (a number), or a URL built as an object rather than a string.

Common situations: Hand-edited evaluate snippets returning `url: new URL(...)` instead of `.href`; automation wrapping the href in a DOM node; refactors where the tweet permalink became a structured object { pathname, id }.

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/7fb798d132a10497. Report an issue: GitHub.