jackwener/OpenCLI · error · CommandExecutionError
Send button not found
Error message
Send button not found
What it means
A CommandExecutionError thrown by the qoder send command after both send strategies fail: first clicking button[aria-label="Send message"] / button[title="Send message"] via clickFirstScript, then the clickByTextScript fallback with 'Send message' / 'Send' / '发送'. If neither finds a clickable send control, this error is thrown — the text may have been typed but never sent.
Source
Thrown at clis/qoder/quest.js:78
columns: ['Status', 'Length'],
func: async (page, kwargs) => {
const text = String(kwargs?.text || '').trim();
if (!text) throw new ArgumentError('text is required');
const beforeCount = await evaluateQoder(page, QODER_MESSAGE_COUNT_JS);
const typeRes = await evaluateQoder(page, buildQoderInjectTextScript(text));
if (!typeRes?.ok) throw new CommandExecutionError(typeRes?.reason || 'composer type failed', '');
await page.wait(0.3);
// Click Send message
const sendRes = await evaluateQoder(page, clickFirstScript([
'button[aria-label="Send message"]',
'button[title="Send message"]',
]));
if (!sendRes?.ok) {
// Fallback: try clickByText.
const textRes = await evaluateQoder(page, clickByTextScript(['Send message', 'Send', '发送']));
if (!textRes?.ok) throw new CommandExecutionError('Send button not found', '');
}
const afterCount = await waitForMessageCountGrowth(page, beforeCount);
if (Number(afterCount) <= Number(beforeCount)) {
throw new CommandExecutionError('Qoder send did not create a new visible message row');
}
return [{ Status: 'sent', Length: String(text.length) }];
},
});
// -------- ask --------
cli({
site: 'qoder',
name: 'ask',
access: 'write',
description: 'Send a prompt to Qoder and wait up to --timeout seconds for the reply (best-effort: polls for the chat turn count to grow + stabilize).',
domain: 'localhost',
strategy: Strategy.UI,
browser: true,View on GitHub (pinned to 49907e53dc)
Solutions
- Retry with a short wait after typing — the Send button only becomes enabled once the composer registers the injected text.
- Inspect the composer DOM and add the current selector (new aria-label or a form submit selector) to the clickFirstScript selector list.
- Add a keyboard fallback: dispatch an Enter keypress on the composer, which Qoder treats as send.
- Verify text injection succeeded first (composer value non-empty) since a disabled Send is usually a symptom of failed injection, not a missing button.
Example fix
// before
if (!textRes?.ok) throw new CommandExecutionError('Send button not found', '');
// after
if (!textRes?.ok) {
const enterRes = await evaluateQoder(page, pressEnterInComposerScript());
if (!enterRes?.ok) throw new CommandExecutionError('Send button not found', '');
} Defensive patterns
Strategy: fallback
Validate before calling
// Verify injection registered and a send control exists before invoking
const state = await page.evaluate(() => {
const el = document.querySelector('textarea, [contenteditable="true"]');
const hasText = !!el && (el.value || el.innerText || '').trim().length > 0;
const hasSend = !!document.querySelector('button[aria-label="Send message"], button[title="Send message"]');
return { hasText, hasSend };
});
if (!state.hasText || !state.hasSend) throw new Error('Composer empty or Send control missing — send would fail'); Type guard
function hasClickResult(res) {
return typeof res === 'object' && res !== null && res.ok === true;
} Try / catch
try {
await runCli('qoder send', [text]);
} catch (e) {
if (String(e.message).includes('Send button not found')) {
// keyboard fallback: focus composer and press Enter
await focusComposerAndPressEnter();
} else throw e;
} Prevention
- Confirm the composer holds text (Send is disabled when empty) before expecting a click.
- Re-check aria-labels/title attributes after every Qoder update.
- Maintain an Enter-key fallback for icon-only or relabeled send buttons.
- Allow a short post-typing delay so the button transitions to enabled.
When it happens
Trigger: Running `qoder send <text>` when: the composer is empty in Qoder's eyes (injection silently failed or text was rejected), so the Send button is disabled/hidden; Qoder changed the aria-label/title (e.g. to 'Send' or an icon with different metadata); the send control is now an icon-only SVG button with no accessible label or text; or the UI is mid-render.
Common situations: Qoder redesigns replacing the labeled button with an icon-only button lacking aria-label; localized builds where text candidates ('Send message'/'Send'/'发送') don't match; Enter-to-send-only configurations with no visible button; automation racing the composer's enabled state after typing.
Related errors
- Prompt Enhance button not found
- Open Editor button not found
- New Quest button not found
- composer type failed
- Qoder send did not create a new visible message row
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/3af66e24521c94c4.
Report an issue: GitHub.