jackwener/OpenCLI · error · Error
BUTTON_NOT_FOUND: Follow button not on profile page (logged
Error message
BUTTON_NOT_FOUND: Follow button not on profile page (logged out, private account, or selectors changed)
What it means
The injected follow script finds the Follow button by text label, but neither a Follow label nor a Following label was present on the profile page. The library throws a plain Error prefixed BUTTON_NOT_FOUND, listing the plausible causes: logged out, private account, or changed selectors.
Source
Thrown at clis/tiktok/follow.js:54
ensureLoggedInOrThrow();
ensureNoRateLimitOrThrow();
const FOLLOW_LABELS = ['Follow', '关注', 'フォロー'];
const FOLLOWING_LABELS = ['Following', '已关注', 'フォロー中'];
const FRIENDS_LABELS = ['Friends', '互关', 'フレンド'];
const ALREADY_LABELS = FOLLOWING_LABELS.concat(FRIENDS_LABELS);
// Idempotent fast path: already in target state.
if (buttonExists(FRIENDS_LABELS)) {
return [{ username, url: ${JSON.stringify(TIKTOK_HOST)} + '/@' + encodeURIComponent(username), result: 'already-friends' }];
}
if (buttonExists(FOLLOWING_LABELS)) {
return [{ username, url: ${JSON.stringify(TIKTOK_HOST)} + '/@' + encodeURIComponent(username), result: 'already-following' }];
}
const followBtn = findButtonByText(FOLLOW_LABELS);
if (!followBtn) {
throw new Error('BUTTON_NOT_FOUND: Follow button not on profile page (logged out, private account, or selectors changed)');
}
const target = followBtn.closest('button') || followBtn.closest('[role="button"]') || followBtn;
target.click();
// State verification: button text should flip to Following / 已关注 etc.
const flipped = await waitFor(() => buttonExists(ALREADY_LABELS), { timeoutMs: 5000 });
if (!flipped) {
ensureNoRateLimitOrThrow();
throw new Error('STATE_VERIFY_FAIL: follow button did not flip to Following within 5s; relation may not have been recorded');
}
// Re-check rate limit AFTER click — TikTok sometimes flashes captcha
// mid-flight even when the button text appears to flip.
ensureNoRateLimitOrThrow();
return [{
username,View on GitHub (pinned to 49907e53dc)
Solutions
- Verify the Chrome profile is logged in to TikTok before running the follow command
- Open the target profile manually to confirm it's public and shows a Follow button
- Check locale — if the UI is in a language whose label isn't in FOLLOW_LABELS, force en or add the label
- Update the library if TikTok changed the button text/DOM structure
- Catch the error and inspect a page screenshot to see what the profile actually rendered
Example fix
// before
await followUser(page, { username: 'target' });
// after
try {
await followUser(page, { username: 'target' });
} catch (e) {
if (/BUTTON_NOT_FOUND/.test(e.message)) {
await ensureTikTokLogin(page); // re-auth then retry
await followUser(page, { username: 'target' });
} else throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
const btn = await page.evaluate(() => !!document.querySelector('button')) && await page.content().then(html => /Follow|Following|关注/i.test(html));
if (!btn) throw new Error('Follow/Following button text not present — check login state and locale'); Type guard
function isButtonNotFound(e) { return /BUTTON_NOT_FOUND/.test(e.message); } Try / catch
try {
await followUser(page, { username });
} catch (e) {
if (isButtonNotFound(e)) {
await ensureTikTokLogin(page); // most common cause: logged out
await followUser(page, { username });
} else throw e;
} Prevention
- Ensure the profile is logged in before following
- Only target public, non-blocked accounts
- Force an English (or supported) locale so button labels match FOLLOW_LABELS
- Take a screenshot on failure to see what actually rendered
- Update the library when TikTok redesigns button markup
When it happens
Trigger: findButtonByText(FOLLOW_LABELS) returned null on the profile page: not logged in (buttons render differently), the target account is private/blocked/unavailable, the page showed a login wall, or TikTok renamed button labels so FOLLOW_LABELS/FOLLOWING_LABELS no longer match.
Common situations: Session expired so TikTok shows logged-out profile markup, following a private or region-blocked account, non-English locale where button text isn't in FOLLOW_LABELS, or TikTok UI redesign changing button markup.
Related errors
- Favorites button not found - make sure you are logged in
- Like button not found - make sure you are logged in
- No videos found on /explore + suffix
- TikTok returned no notifications
- Search failed: HTTP ${res.status}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/da396feca6a9744b.
Report an issue: GitHub.