jackwener/OpenCLI · error · TimeoutError

${result.message} Check the profile before retrying; the blo

Error message

${result.message} Check the profile before retrying; the block may already have succeeded.

What it means

When the in-page block script reports ok:false without unconfirmed=true, the CLI throws CommandExecutionError(result.message, 'Nothing changed. Open the profile in the browser and retry.'). This means the block flow failed before the destructive write began (unlike the unconfirmed TimeoutError case), so no state change happened and the failure is safe to retry after manual inspection.

Source

Thrown at clis/twitter/block.js:103

                return { ok: false, message: 'Block confirmation dialog did not appear.' };
            }
            writeStarted = true;
            confirmBtn.click();
            await new Promise(r => setTimeout(r, 1500));

            // Verify
            const verify = getPrimary()?.querySelector('[data-testid$="-unblock"]');
            if (verify) {
                return { ok: true, message: 'Successfully blocked @${username}.' };
            } else {
                return { ok: false, unconfirmed: true, message: 'Block action initiated but UI did not update.' };
            }
        } catch (e) {
            return { ok: false, unconfirmed: writeStarted, message: e.toString() };
        }
    })()`);
        if (result.unconfirmed) {
            throw new TimeoutError('twitter block confirmation', 1.5, `${result.message} Check the profile before retrying; the block 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 target profile in the controlled browser to confirm it exists and you are logged in.
  2. Re-run the command; transient render delays are the most common cause of missing menus/confirm dialog.
  3. Verify the username (without @) is correct and the account is not suspended/deleted.
  4. Update the CLI if Twitter changed data-testid attributes (userActions, confirmationSheetConfirm) or menu labels.

Example fix

// before
await cli.run('twitter block @user');
// after
try {
  await cli.run('twitter block @user');
} catch (e) {
  console.error(e.message, e.hint || ''); // inspect, then retry after checking profile
  await cli.run('browser open https://x.com/user');
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: confirm the profile exists and is viewable
const res = await page.goto('https://x.com/' + username);
if (!res || res.status() === 404) throw new Error('Profile ' + username + ' not found');

Type guard

function isBlockFailure(result) {
  return result !== null && typeof result === 'object' && result.ok === false && result.unconfirmed !== true;
}

Try / catch

try {
  await cli.run('twitter block @user');
} catch (e) {
  if (/Nothing changed/.test(e.message)) {
    console.warn('Block not applied:', e.message, e.hint);
    await verifyProfileManually('user');
    return cli.run('twitter block @user'); // retry-safe: no write started
  }
  throw e;
}

Prevention

When it happens

Trigger: The page script returned { ok:false, message } from any of its guard branches: profile surface not found, user actions menu missing, Block menu item not found, or the confirmation dialog did not appear — with writeStarted still false.

Common situations: Not logged in (profile surface absent), target username doesn't exist or is suspended, Twitter UI variant hides the userActions button, localized UI text not matched by the block-text heuristic, or a slow render so menus never appear within the ~10s polling window.

Related errors


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