jackwener/OpenCLI · error · CommandExecutionError

Qoder send did not create a new visible message row

Error message

Qoder send did not create a new visible message row

What it means

A CommandExecutionError thrown by qoder send as a post-send verification failure. After clicking Send (both strategies), waitForMessageCountGrowth polls QODER_MESSAGE_COUNT_JS for up to 5s; if the visible message-row count never exceeds the pre-send count, the command concludes the message never appeared and throws. This is the safety net that catches 'clicked send but nothing was actually sent'.

Solutions

  1. Open Qoder and visually confirm whether the message actually appeared — if it did, the count selector in QODER_MESSAGE_COUNT_JS is stale; update it to the current message-list markup.
  2. Increase the 5s wait window (timeoutMs in waitForMessageCountGrowth) for slow/large messages.
  3. Ensure text injection truly registered (check composer empties on send) before clicking Send; re-inject if the composer still holds text.
  4. Close extra Qoder windows and verify evaluateQoder targets the same frame for counting and sending.

Example fix

// before
const afterCount = await waitForMessageCountGrowth(page, beforeCount);
if (Number(afterCount) <= Number(beforeCount)) {
    throw new CommandExecutionError('Qoder send did not create a new visible message row');
}
// after
const afterCount = await waitForMessageCountGrowth(page, beforeCount, 15000); // longer window
if (Number(afterCount) <= Number(beforeCount)) {
    throw new CommandExecutionError('Qoder send did not create a new visible message row');
}
Defensive patterns

Strategy: retry

Validate before calling

// Sanity-check the message-count selector still matches before relying on send verification
const count = await page.evaluate(() => QODER_MESSAGE_COUNT_JS);
if (count === null || Number.isNaN(Number(count))) throw new Error('Message-count selector stale — update QODER_MESSAGE_COUNT_JS');

Type guard

function countGrew(before, after) {
  const b = Number(before), a = Number(after);
  return Number.isFinite(b) && Number.isFinite(a) && a > b;
}

Try / catch

try {
  await runCli('qoder send', [text]);
} catch (e) {
  if (String(e.message).includes('did not create a new visible message row')) {
    await sleep(3000);
    await runCli('qoder send', [text]); // one retry; if it recurs, check Qoder UI manually
  } else throw e;
}

Prevention

When it happens

Trigger: Running `qoder send <text>` when: the send click landed on a disabled button (injection never registered); Qoder treats the injected text as empty and ignores Enter/click; QODER_MESSAGE_COUNT_JS's row selector no longer matches the message list after an update, so growth is invisible; the message was sent into a different Quest/window than the one being counted; or generation errors client-side so no user row renders.

Common situations: Qoder updates renaming message-row classes, breaking the count selector and producing false negatives even though sending worked; rate limits or network errors preventing message creation; automated sends racing the composer's enabled state; multiple open Qoder windows causing count/verify to run in different frames.

Related errors


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

Appendix: source

Thrown at clis/qoder/quest.js:82

        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,
    args: [
        { name: 'text', positional: true, required: true, help: 'Prompt text' },
        { name: 'timeout', type: 'int', required: false, default: 120, help: 'Max seconds to wait' },
    ],

View on GitHub (pinned to 49907e53dc)