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
- Return a string from the page script: `url: location.href` or `url: anchor.href` rather than the object.
- Coerce before returning: `url: String(rawUrl)`.
- 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
- Return href strings (element.href, location.href), never URL/Location objects, from page.evaluate.
- Coerce with String(rawUrl) at the boundary inside the page script.
- Review any modified evaluate snippet for object-valued url fields before merging.
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- ${context} returned a malformed message.
- Unexpected 12306 probe: ${JSON.stringify(probe)}
- Waiting for 12306 tk auth cookie
- x.com
- Nothing changed. Open the tweet in the browser and retry.
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/7fb798d132a10497.
Report an issue: GitHub.