Yeachan-Heo/oh-my-codex · warning · Error

sendToWorker: submit_failed (trigger text still visible afte

Error message

sendToWorker: submit_failed (trigger text still visible after retries)

What it means

Strict-mode failure after the submit retry loop: the trigger text is still visible in the captured pane content, meaning the worker (e.g. Codex CLI) apparently never consumed the submitted line. By default the library fails open because workers often keep the last submitted line visible; setting OMX_TEAM_STRICT_SUBMIT=1 enables this hard failure for debugging.

Source

Thrown at src/team/tmux-session.ts:3841

  )) return;

  // Adaptive escalation for "likely unsent trigger text at ready prompt" cases:
  // clear line, re-send trigger, then re-submit with deterministic Enter rounds.
  const latestCapture = await capturePaneAsync(resolveTarget);
  if (shouldAttemptAdaptiveRetry(strategy, paneBusy, submitPlan.allowAdaptiveRetry, latestCapture || null, text)) {
    // Keep this branch non-interrupting to avoid canceling active turns on false positives.
    await sendKeyAsync(resolveTarget, 'C-u');
    await sleep(80);
    await sendLiteralTextOrThrow(resolveTarget, text);
    await sleep(120);
    if (await attemptSubmitRounds(resolveTarget, text, 4, false, submitPlan.submitKeyPressesPerRound)) return;
  }

  // Fail-open by default: Codex may keep the last submitted line visible even after executing it.
  // If you need strictness for debugging, set OMX_TEAM_STRICT_SUBMIT=1.
  const strict = process.env.OMX_TEAM_STRICT_SUBMIT === '1';
  if (strict) {
    throw new Error('sendToWorker: submit_failed (trigger text still visible after retries)');
  }

  // One last best-effort double Enter nudge, then verify.
  await sendKeyAsync(resolveTarget, 'Enter');
  await sleep(120);
  await sendKeyAsync(resolveTarget, 'Enter');

  // Post-submit verification: wait briefly and confirm the worker consumed the
  // trigger (draft disappeared or active-task indicator appeared). Fixes #391.
  await sleep(300);
  const [verifyCapture, verifyVisibleCapture] = await Promise.all([
    capturePaneAsync(resolveTarget),
    captureVisiblePaneAsync(resolveTarget),
  ]);
  if (verifyCapture) {
    if (paneHasActiveTask(verifyCapture)) return;
    if (
      !normalizeWorkerTriggerForDraftMatch(verifyCapture).includes(normalizeWorkerTriggerForDraftMatch(text))

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. If strictness isn't required, unset OMX_TEAM_STRICT_SUBMIT (default fail-open behavior)
  2. Increase retry counts / delays before verification so slow workers can consume input
  3. Inspect the pane capture to confirm the worker is actually stuck vs just echoing the line
  4. Ensure Enter is sent when the worker is at a prompt (wait for paneLooksReady)

Example fix

// before
OMX_TEAM_STRICT_SUBMIT=1 node orchestrator.js

// after
// accept fail-open default, or wait for readiness:
await waitForPaneReady(resolveTarget);
await sendToWorker(resolveTarget, text); // strict off
Defensive patterns

Strategy: retry

Validate before calling

delete process.env.OMX_TEAM_STRICT_SUBMIT; // use fail-open default

Try / catch

try { await submitWorker(resolveTarget, text); } catch (err) { if (!/submit_failed/.test(String(err))) throw err; await sleep(1000); await submitWorker(resolveTarget, text); }

Prevention

When it happens

Trigger: Running with OMX_TEAM_STRICT_SUBMIT=1 and, after all Enter retries plus verification, the normalized pane capture still shows the trigger text — worker never executed it (hung, busy, wrong pane, or input dropped).

Common situations: Enabling strict mode while a worker keeps echo of submitted lines on screen; worker stuck mid-tool-call; Enter keys sent while worker not reading stdin; slow worker where verification runs before consumption.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/e42d49edb0a7fcb0. Report an issue: GitHub.