jackwener/OpenCLI · error · CommandExecutionError
Click on account button "${label}" failed
Error message
Click on account button "${label}" failed What it means
In the Qoder 'account' command, after detecting (or being given) the username label, the adapter clicks it with clickByTextScript([label], {exact:true, maxLen:60}). If that click reports {ok:false}, it throws CommandExecutionError(`Click on account button "${label}" failed`). Detection succeeded but the exact-text click could not find/click the matching button.
Source
Thrown at clis/qoder/ui.js:278
label = await evaluateQoder(page, `(() => {
${IS_VISIBLE_JS}
const btns = Array.from(document.querySelectorAll('button')).filter(isVisible);
const known = new Set(['Pin', 'Copy', 'New Quest', 'Search', 'Settings', 'View all', 'Knowledge', 'Marketplace', 'Credits Usage', 'Open Editor', 'Add Workspace', 'More Actions', 'Send message', 'Prompt Enhance', 'Voice input', 'button']);
const candidate = btns.find((b) => {
const tx = (b.innerText || '').trim();
if (!tx || tx.length > 30 || tx.includes('⌘') || known.has(tx)) return false;
if (/^(New|Open|Add|Save|Edit|Cancel|OK|Close)/.test(tx)) return false;
return true;
});
return candidate ? (candidate.innerText || '').trim() : '';
})()`);
}
if (!label) {
throw new CommandExecutionError('No account button detected. Pass --username <name> explicitly.', '');
}
// Click the username button
const clickRes = await evaluateQoder(page, clickByTextScript([label], { exact: true, maxLen: 60 }));
if (!clickRes?.ok) throw new CommandExecutionError(`Click on account button "${label}" failed`, '');
await page.wait(0.5);
const items = requireArrayResult(await evaluateQoder(page, `(() => {
${IS_VISIBLE_JS}
const popovers = Array.from(document.querySelectorAll('[role="menu"], [role="dialog"], [class*="popover"i], [class*="dropdown"i]')).filter(isVisible)
.filter((el) => { const r = el.getBoundingClientRect(); return r.width < 500 && r.height < 600; });
if (!popovers.length) return [];
const pop = popovers[popovers.length - 1];
return Array.from(pop.querySelectorAll('button, [role="menuitem"], a'))
.filter(isVisible)
.map((b) => (b.innerText || b.textContent || '').trim().replace(/\\s+/g, ' '))
.filter(Boolean);
})()`), 'qoder account');
try { await page.evaluate(`document.body.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));`); } catch {}
const rows = [{ Field: 'Username', Value: label }];
(items || []).slice(0, 20).forEach((item, i) => {
rows.push({ Field: `Item[${i + 1}]`, Value: item });
});
return rows;View on GitHub (pinned to 49907e53dc)
Solutions
- Pass a --username value exactly as displayed in the UI (same case, no truncation), or shorten to the displayed form.
- Fall back to substring matching (exact:false) when exact click fails.
- Re-detect and click in one pass to avoid re-render races.
- Increase maxLen if the display name is longer than 60 characters.
- Inspect the button's innerText via CDP DevTools and use that exact string.
Example fix
// before
clickByTextScript([label], { exact: true, maxLen: 60 })
// after: fallback to substring match
let clickRes = await evaluateQoder(page, clickByTextScript([label], { exact: true, maxLen: 60 }));
if (!clickRes?.ok) clickRes = await evaluateQoder(page, clickByTextScript([label], { exact: false, maxLen: 120 })); Defensive patterns
Strategy: validation
Validate before calling
// Ensure the username matches the exact UI text before clicking
function normalizeUsername(name) {
const s = String(name).replace(/\s+/g, ' ').trim();
if (!s || s.length > 60) {
throw new Error('Username must be non-empty and <= 60 chars, exactly as shown in the Qoder UI.');
}
return s;
} Type guard
function isValidUsernameLabel(label) {
return typeof label === 'string' && label.trim().length > 0 && label.length <= 60;
} Try / catch
try {
await cli.run(['qoder', 'account', '--username', label]);
} catch (e) {
if (String(e.message).includes('Click on account button')) {
// retry with the exact innerText copied from the Qoder UI
console.error('Use the exact display name as rendered (whitespace/emoji included).');
} else throw e;
} Prevention
- Copy the --username value exactly from the rendered button text
- Avoid passing truncated or full-length names when the UI truncates them
- Whitespace-normalize usernames before passing them
- If auto-detected, prefer using the same detection path end-to-end
When it happens
Trigger: The label scraped from a candidate button does not exactly equal any clickable element's trimmed innerText (detection and click use different matching: detection is heuristic, click uses exact match with maxLen 60); username longer than 60 chars; whitespace/emoji differences in the rendered text; UI re-rendered between detection and click.
Common situations: Username containing trailing whitespace, newlines, or an avatar glyph so exact match fails; long display names truncated in UI but passed in full via --username; Qoder re-render replacing the element between the two evaluate calls.
Related errors
- Knowledge button not found
- Marketplace button not found
- Credits Usage not visible
- View all button not visible
- Add Workspace button not found
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/0e1f6fc4783b0084.
Report an issue: GitHub.