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

When the in-page follow script completed without an unconfirmed write but reported ok:false, the command surfaces the script's own message via CommandExecutionError with the fixed hint 'Nothing changed. Open the profile in the browser and retry.' This means the follow flow ran, determined no follow action was performed (e.g. already following, button not in expected state, or a caught in-page error), and no state was mutated.

Source

Thrown at clis/twitter/follow.js:66

            followBtn.click();
            await new Promise(r => setTimeout(r, 1500));

            // Verify
            const verify = document.querySelector('[data-testid$="-unfollow"]');
            if (verify) {
                return { ok: true, message: 'Successfully followed @${username}.' };
            } else {
                return { ok: false, unconfirmed: true, message: 'Follow action initiated but UI did not update.' };
            }
        } catch (e) {
            return { ok: false, unconfirmed: writeStarted, message: e.toString() };
        }
    })()`);
        if (result.unconfirmed) {
            throw new TimeoutError('twitter follow confirmation', 1.5, `${result.message} Check the profile before retrying; the follow 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

  1. Open the profile in the browser and manually inspect: is it already followed, pending, or blocked?
  2. Verify the username is correct and the account exists (404 profiles produce a failed flow).
  3. Check for rate-limit or interstitial modals on x.com; wait and retry later if limited.
  4. If the button/UI has changed, update the CLI's in-page script or report the X DOM change.

Example fix

// before
opencli twitter follow privateacct   // 'Pending' state -> ok:false
// after
// confirm in browser; for pending/already-following accounts skip the retry
opencli twitter follow publicacct
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight checks that avoid ok:false outcomes
async function canFollow(page, username) {
  if (!/^[A-Za-z0-9_]{1,15}$/.test(username)) return { ok: false, reason: 'invalid username' };
  await page.goto(`https://x.com/${username}`);
  // Ensure no interstitial and the follow button is present/affordant
  return { ok: true };
}

Type guard

function isSuccessfulFollowResult(r) {
  return typeof r === 'object' && r !== null && r.ok === true;
}

Try / catch

try {
  await follow(username);
} catch (e) {
  if (e.code === 'COMMAND_EXEC' && e.message.includes('Nothing changed')) {
    // No mutation happened: inspect profile state (already following / pending / blocked / rate-limited)
    const state = await inspectProfileFollowState(username);
    console.error(`Follow not performed (${state}); resolve in browser before retrying.`);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: The in-page evaluate returned {ok:false, message} — e.g. the follow button was not found in the expected state, the account was already followed, a modal (rate limit, login prompt) intercepted the flow, or an in-page exception occurred before the write started.

Common situations: Targeting a private/protected account where the button is 'Pending' rather than 'Follow'; X UI changes renaming the button or its data-testid; hitting X's follow rate limits; trying to follow an account that blocked you or does not exist.

Related errors


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