Hmbown/CodeWhale · warning
{INITIAL_PROMPT_DEFERRED_STATUS}
Error message
{INITIAL_PROMPT_DEFERRED_STATUS} What it means
prepare_user_dispatch refuses to send a queued user message while the redaction gate is active (app.redaction_gate == true). The gate blocks dispatch until the user resolves the model-bound masking confirmation ("confirm" or "keep masking"). The error message is the INITIAL_PROMPT_DEFERRED_STATUS constant: "Initial prompt ready; complete setup to send it" — it signals the initial prompt is held, not lost.
Solutions
- Resolve the redaction gate prompt in the UI (choose "confirm" or "keep masking") — the deferred prompt is then sent automatically.
- Check app.redaction_gate before dispatch and route the message into the deferred queue instead of calling prepare_user_dispatch.
- In tests or scripts, simulate the gate resolution (or set app.redaction_gate = false after handling) before dispatching.
- The prompt is not lost: it remains queued and dispatches once setup completes; no user action beyond the gate is needed.
Example fix
// before
prepare_user_dispatch(app, config, message)?;
// after
if app.redaction_gate {
app.status_message = Some(INITIAL_PROMPT_DEFERRED_STATUS.to_string());
return Ok(UserDispatchPrepare::Deferred(message));
}
prepare_user_dispatch(app, config, message)?; Defensive patterns
Strategy: validation
Validate before calling
if app.redaction_gate {
app.status_message = Some(INITIAL_PROMPT_DEFERRED_STATUS.to_string());
return Ok(UserDispatchPrepare::Deferred(message));
} Type guard
fn dispatch_allowed(app: &App) -> bool { !app.redaction_gate } Try / catch
match prepare_user_dispatch(app, config, message) {
Err(err) if err.to_string() == INITIAL_PROMPT_DEFERRED_STATUS => {
// expected: gate pending — keep the message queued, no user alarm
}
other => other?,
} Prevention
- Resolve the redaction gate (confirm / keep masking) before expecting the initial prompt to send.
- In automated flows/tests, simulate the gate resolution before dispatching prompts.
- Treat the message as deferred, not failed: it sends automatically once the gate clears.
When it happens
Trigger: Calling prepare_user_dispatch (from dispatch_user_message_with_recovery / start_user_dispatch) when app.redaction_gate is set — i.e. the first prompt was submitted before the user completed the redaction-gate confirmation flow, so the message is intentionally deferred.
Common situations: A user launching Codewhale with an initial prompt (CLI arg or restored input) while the model-bound redaction decision prompt is pending; automated tests dispatching prompts without resolving the gate.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Initial prompt ready; complete setup to send it
- dispatch task was lost
- for
- No loaded config file can receive this confirmation
- unavailable credential
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/8421c47e4d5865a4.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/ui/dispatch.rs:577
warning: Some(
"message_submit hook executor did not run; submission continued because no strict gate matched"
.to_string(),
),
}
} else {
crate::hooks::MessageSubmitOutcome::Blocked {
reason: "message_submit hook executor did not run; a strict gate blocked submission"
.to_string(),
}
}
}
pub(crate) fn prepare_user_dispatch(
app: &mut App,
config: &Config,
message: QueuedMessage,
) -> Result<UserDispatchPrepare> {
anyhow::ensure!(!app.redaction_gate, "{INITIAL_PROMPT_DEFERRED_STATUS}");
let _ = app.maybe_nudge_for_planning_prompt(&message.display);
let _ = app.maybe_nudge_plugin_for_prompt(&message.display);
// Plan paused-command changes without touching App or the engine pause
// gate. Route selection can await and client preflight can fail; neither
// may resume or discard a paused command unless a turn is ready to send.
let paused_dispatch = plan_paused_command_message(app, &message.display);
let cwd = std::env::current_dir().ok();
// One cache for this submit: the references pass and the payload pass
// otherwise each shell out for `@git`/`@diff`, making git compute a large
// working-tree diff twice to attach it once (#4067 review follow-up).
let mut git_cache = crate::tui::git_mention::GitMentionCache::default();
let completion_index = app.composer.mention_discovery.fuzzy_candidates(
&app.workspace,
&app.composer.mention_cwd,
app.mention_walk_depth,
app.workspace_follow_symlinks,View on GitHub (pinned to 433685b202)