jackwener/OpenCLI · error · CommandExecutionError

Nothing changed. Open the tweet in the browser and retry.

Error message

Nothing changed. Open the tweet in the browser and retry.

What it means

When the in-page unlike script returns `ok: false` (and `unconfirmed` is falsy), the CLI wraps the page's `result.message` in a CommandExecutionError with the remediation hint 'Nothing changed. Open the tweet in the browser and retry.' Unlike the confirmation timeout, this path means the script deterministically failed BEFORE any write was started — the unlike was definitely not applied.

Source

Thrown at clis/twitter/unlike.js:77

            await new Promise(r => setTimeout(r, 1000));

            // Verify success by checking if the 'like' button reappeared
            const verifyArticle = findTargetArticle() || targetArticle;
            const verifyBtn = verifyArticle?.querySelector('[data-testid="like"]');
            if (verifyBtn) {
                return { ok: true, message: 'Tweet successfully unliked.' };
            } else {
                return { ok: false, unconfirmed: true, message: 'Unlike action was initiated but UI did not update as expected.' };
            }
        } catch (e) {
            return { ok: false, unconfirmed: writeStarted, message: e.toString() };
        }
    })()`);
        if (result.unconfirmed) {
            throw new TimeoutError('twitter unlike confirmation', 1, `${result.message} Check the tweet before retrying; the unlike may already have succeeded.`);
        }
        if (!result.ok) {
            throw new CommandExecutionError(result.message, 'Nothing changed. Open the tweet in the browser and retry.');
        }
        await page.wait(2);
        return [{
                status: 'success',
                message: result.message
            }];
    }
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Open the tweet URL in the opencli browser, confirm you are logged in and can see the Unlike button, then re-run the command.
  2. Re-authenticate the x.com session (log in again) if the buttons are missing due to a logged-out state.
  3. Verify the tweet URL is valid and the tweet still exists (parseTweetUrl resolved it, but the tweet may be deleted).
  4. If it persists, inspect for X.com DOM/data-testid changes and update selectors.

Example fix

// before
opencli twitter unlike https://x.com/user/status/123   // fails: logged out, no Unlike button
// after
opencli browser login x.com                              # restore session
opencli twitter unlike https://x.com/user/status/123
Defensive patterns

Strategy: validation

Validate before calling

// pre-check: logged in and the unlike control is reachable
const ready = await page.evaluate(`!!document.querySelector('[data-testid="AppTabBar_Profile_Link"]')`);
if (!ready) throw new Error('Not logged into x.com; unlike will fail');

Type guard

function isDeterministicUnlikeFailure(e) {
  return e instanceof CommandExecutionError && /Nothing changed/.test(String(e.hint || e.message));
}

Try / catch

try {
  await cli.run(['twitter', 'unlike', tweetUrl]);
} catch (e) {
  if (isDeterministicUnlikeFailure(e)) {
    await ensureXLogin();        // restore session
    await cli.run(['twitter', 'unlike', tweetUrl]);
  } else throw e;
}

Prevention

When it happens

Trigger: The Unlike button was not found after the 10s poll ('Could not find the Unlike button... Are you logged in?'), typically because the user is logged out or the tweet/article for the given status id never rendered; any other in-page failure captured before `writeStarted = true`.

Common situations: Expired or missing x.com login session so the unlike control is absent; wrong/deleted tweet URL; protected tweet or conversation page where the target article is not in the DOM; rate limiting hiding action buttons.

Related errors


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