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'.

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)

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.