{"record":{"id":"677c7efe311049cc","repo":"jackwener/OpenCLI","slug":"codex-send-was-not-submitted","errorCode":null,"errorMessage":"Codex send was not submitted.","messagePattern":"Codex send was not submitted\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/codex/send.js","lineNumber":223,"sourceCode":"                    `expected=${picked.title} ${describeComposerState(applied ?? { text: '', chips: [] })}`,\n                );\n            }\n        }\n        await page.pressKey('Enter');\n        let state = await pollComposerState(page);\n        if (state.text) {\n            // The picker consumes Enter to insert the highlighted entry, so a\n            // still-loaded composer is either the untouched draft or the chip\n            // the picker resolved. Anything else was rewritten: never submit.\n            const slashToken = /^\\/\\S+$/.test(textToInsert) ? textToInsert.slice(1) : '';\n            const chipLabel = picked ? picked.title : slashToken;\n            const unchangedDraft = state.chips.length === 0 && state.text === String(textToInsert).trim();\n            const pickerResolvedCommand = chipLabel !== ''\n                && state.chips.length === 1\n                && state.nonChipText === ''\n                && chipMatchesLabel(state.chips[0], chipLabel);\n            if (!unchangedDraft && !pickerResolvedCommand) {\n                throw new CommandExecutionError(\n                    'Codex send was not submitted.',\n                    `The composer now holds ${describeComposerState(state)}. Re-run with --pick <label> or press Escape in Codex first.`,\n                );\n            }\n            await page.pressKey('Enter');\n            state = await pollComposerState(page);\n            if (state.text) {\n                throw new CommandExecutionError('Codex send was not verified.', `The composer still holds an unsent draft: ${describeComposerState(state)}`);\n            }\n        }\n        return [\n            {\n                Status: 'Success',\n                Project: selected?.project || '',\n                Conversation: selected?.conversation || '',\n                InjectedText: textToInsert,\n            },\n        ];","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/codex/send.js#L205-L241","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Press Escape in Codex to clear the composer, then re-run the command.","Re-run with `--pick <label>` so the command goes through the picker flow explicitly.","Manually clear the composer of leftover chips/text before retrying.","Ensure no concurrent typing/automation is interacting with the Codex composer."],"exampleFix":"// before (dirty composer)\nawait codexSend(page, '/review'); // composer had leftover text\n// after\ncodexSend(page, '/review', { preflight: async (p) => { await p.pressKey('Escape'); } });","handlingStrategy":"validation","validationCode":"// Check composer is clean before sending\nconst state = await readComposerState(page);\nif (state.chips.length > 0 || state.text.trim() !== '') {\n  throw new Error('Composer not clean; press Escape in Codex first');\n}","typeGuard":"const isCleanComposer = (s) => s && s.chips.length === 0 && typeof s.text === 'string' && s.text.trim() === '';","tryCatchPattern":"try {\n  await codexSend({ text });\n} catch (e) {\n  if (String(e.message).includes('send was not submitted')) {\n    await page.pressKey('Escape'); // clear composer, then retry\n  } else throw e;\n}","preventionTips":["Always start from an empty composer (Escape first).","Never interleave manual typing with automated sends.","Use `--pick <label>` for slash commands instead of typing raw text.","Check the error's composer-state detail to see what was left behind."],"tags":["codex","composer","send","automation"],"backgroundTag":"composer-state-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}