jackwener/OpenCLI · error · CommandExecutionError
Nothing changed. Open the profile in the browser and retry.
Error message
Nothing changed. Open the profile in the browser and retry.
What it means
CommandExecutionError (code COMMAND_EXEC) raised by `twitter unblock` when the in-page script completed but returned ok:false with no pending write (unconfirmed=false), meaning the unblock action definitively did not go through. The error message is the page script's own failure text; the hint 'Nothing changed. Open the profile in the browser and retry.' tells the user the state is untouched. Unlike the timeout case, no partial write occurred, so retrying is safe.
Source
Thrown at clis/twitter/unblock.js:81
confirmBtn.click();
await new Promise(r => setTimeout(r, 1000));
// Verify
const verify = getPrimary()?.querySelector('[data-testid$="-follow"]');
if (verify) {
return { ok: true, message: 'Successfully unblocked @${username}.' };
} else {
return { ok: false, unconfirmed: true, message: 'Unblock action initiated but UI did not update.' };
}
} catch (e) {
return { ok: false, unconfirmed: writeStarted, message: e.toString() };
}
})()`);
if (result.unconfirmed) {
throw new TimeoutError('twitter unblock confirmation', 1, `${result.message} Check the profile before retrying; the unblock may already have succeeded.`);
}
if (!result.ok) {
throw new CommandExecutionError(result.message, 'Nothing changed. Open the profile in the browser and retry.');
}
await page.wait(2);
return [{
status: 'success',
message: result.message
}];
}
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Read the underlying result.message in the error output to see which in-page step failed
- Open https://x.com/<username> in the browser to confirm the page renders normally and you are logged in, then retry
- If selectors consistently fail, suspect an X markup change — update or report the library
- Verify you are actually in a blocked state with that user (the unblock control may not exist otherwise)
Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: confirm the profile renders and you are blocked by/in that state
await page.goto(`https://x.com/${username}`);
await page.waitForSelector('[data-testid="primaryColumn"]', { timeout: 10000 }); Type guard
function isCommandExecError(e) { return e && e.code === 'COMMAND_EXEC'; } Try / catch
try {
await cli.run(['twitter', 'unblock', user]);
} catch (e) {
if (e.code === 'COMMAND_EXEC' && /Nothing changed/.test(e.hint || '')) {
// safe to retry: no partial write occurred
console.error(`Unblock failed cleanly: ${e.message} — fix the cause and retry`);
} else throw e;
} Prevention
- Read the wrapped result.message to diagnose which in-page step failed
- Confirm the page loads logged-in in a real browser before scripting writes
- Verify the blocked relationship actually exists so the control is present
- Update the library when X changes profile markup (selectors break cleanly here)
When it happens
Trigger: The evaluate()'d unblock script hit its catch block before any click (writeStarted=false) — e.g. the unblock button/confirm element was not found or the script threw early — and returned {ok:false, unconfirmed:false}, triggering CommandExecutionError with the script's error message.
Common situations: X changed the profile-page button markup so selectors fail; user is not actually blocked by/from that state so the control is absent; page loaded an error or login wall; logged-out session rendering a different profile layout.
Related errors
- Nothing changed. Open the tweet in the browser and retry.
- Nothing changed. Open the profile in the browser and retry.
- Browser session required for twitter follow-batch
- Browser session required for twitter follow
- Nothing changed. Open the profile in the browser and retry.
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/2c6fc7d6e80c120b.
Report an issue: GitHub.