jackwener/OpenCLI · error · CommandExecutionError

Codex send was not submitted.

Error message

Codex send was not submitted.

What it means

After pressing Enter the first time, the library re-reads the composer state. A submitted command must either leave the draft unchanged (`unchangedDraft`: no chips and original text intact, meaning Enter opened the picker instead) or resolve to exactly one chip with no other text (`pickerResolvedCommand`). Anything else means the composer was mutated unexpectedly and the send cannot proceed safely.

Source

Thrown at clis/codex/send.js:223

                    `expected=${picked.title} ${describeComposerState(applied ?? { text: '', chips: [] })}`,
                );
            }
        }
        await page.pressKey('Enter');
        let state = await pollComposerState(page);
        if (state.text) {
            // The picker consumes Enter to insert the highlighted entry, so a
            // still-loaded composer is either the untouched draft or the chip
            // the picker resolved. Anything else was rewritten: never submit.
            const slashToken = /^\/\S+$/.test(textToInsert) ? textToInsert.slice(1) : '';
            const chipLabel = picked ? picked.title : slashToken;
            const unchangedDraft = state.chips.length === 0 && state.text === String(textToInsert).trim();
            const pickerResolvedCommand = chipLabel !== ''
                && state.chips.length === 1
                && state.nonChipText === ''
                && chipMatchesLabel(state.chips[0], chipLabel);
            if (!unchangedDraft && !pickerResolvedCommand) {
                throw new CommandExecutionError(
                    'Codex send was not submitted.',
                    `The composer now holds ${describeComposerState(state)}. Re-run with --pick <label> or press Escape in Codex first.`,
                );
            }
            await page.pressKey('Enter');
            state = await pollComposerState(page);
            if (state.text) {
                throw new CommandExecutionError('Codex send was not verified.', `The composer still holds an unsent draft: ${describeComposerState(state)}`);
            }
        }
        return [
            {
                Status: 'Success',
                Project: selected?.project || '',
                Conversation: selected?.conversation || '',
                InjectedText: textToInsert,
            },
        ];

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Press Escape in Codex to clear the composer, then re-run the command.
  2. Re-run with `--pick <label>` so the command goes through the picker flow explicitly.
  3. Manually clear the composer of leftover chips/text before retrying.
  4. Ensure no concurrent typing/automation is interacting with the Codex composer.

Example fix

// before (dirty composer)
await codexSend(page, '/review'); // composer had leftover text
// after
codexSend(page, '/review', { preflight: async (p) => { await p.pressKey('Escape'); } });
Defensive patterns

Strategy: validation

Validate before calling

// Check composer is clean before sending
const state = await readComposerState(page);
if (state.chips.length > 0 || state.text.trim() !== '') {
  throw new Error('Composer not clean; press Escape in Codex first');
}

Type guard

const isCleanComposer = (s) => s && s.chips.length === 0 && typeof s.text === 'string' && s.text.trim() === '';

Try / catch

try {
  await codexSend({ text });
} catch (e) {
  if (String(e.message).includes('send was not submitted')) {
    await page.pressKey('Escape'); // clear composer, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: Composer state after Enter matches neither `unchangedDraft` nor `pickerResolvedCommand` — e.g. partial text remains alongside a chip, multiple chips exist, or the draft text was altered by Codex (autocorrect, formatting, pre-filled content).

Common situations: Composer already contained leftover text/chips from a previous failed attempt; Codex converted the slash command into something other than a single chip; user (or another automation) typed into the composer mid-send.

Related errors


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