zellij-org/zellij · error · anyhow::Error
SkipConfirm missing action
Error message
SkipConfirm missing action
What it means
Raised while converting an incoming protobuf IPC Action of type SkipConfirm into zellij's internal Action enum (zellij-utils/ipc/protobuf_conversion.rs). The SkipConfirm message wraps the action that should run without its confirmation prompt; the nested `action` field is a proto3 message field, hence optional on the wire. If a client sends SkipConfirm with the inner action unset, the .ok_or_else() here rejects the conversion and the action is never dispatched.
Source
Thrown at zellij-utils/src/ipc/protobuf_conversion.rs:2602
})
},
ActionType::MouseEvent(mouse_event_action) => {
Ok(crate::input::actions::Action::MouseEvent {
event: mouse_event_action
.event
.ok_or_else(|| anyhow!("MouseEvent missing event"))?
.try_into()?,
})
},
ActionType::Copy(_) => Ok(crate::input::actions::Action::Copy),
ActionType::Confirm(_) => Ok(crate::input::actions::Action::Confirm),
ActionType::Deny(_) => Ok(crate::input::actions::Action::Deny),
ActionType::SkipConfirm(skip_confirm_action) => {
Ok(crate::input::actions::Action::SkipConfirm {
action: Box::new(
skip_confirm_action
.action
.ok_or_else(|| anyhow!("SkipConfirm missing action"))?
.as_ref()
.clone()
.try_into()?,
),
})
},
ActionType::SearchInput(search_input_action) => {
Ok(crate::input::actions::Action::SearchInput {
input: search_input_action
.input
.into_iter()
.map(|b| b as u8)
.collect(),
})
},
ActionType::Search(search_action) => Ok(crate::input::actions::Action::Search {
direction: proto_i32_to_search_direction(search_action.direction)?,
}),View on GitHub (pinned to 98a0837077)
Solutions
- Populate the nested action field: SkipConfirm { action: <some Action> } before sending
- Regenerate the client's protobuf stubs from the zellij version the server runs (schema drift is the usual culprit)
- Match client and server versions (same zellij release on both sides)
- If you control the server loop, log-and-drop the malformed action instead of propagating the error
Example fix
// before (prost client)
let mut a = ProtobufAction::default();
a.action_type = Some(ActionType::SkipConfirm(SkipConfirmAction::default())); // inner action unset
// after
let mut inner = ProtobufAction::default();
inner.action_type = Some(ActionType::Write(WriteAction { characters: "y".into() }));
let mut a = ProtobufAction::default();
a.action_type = Some(ActionType::SkipConfirm(SkipConfirmAction { action: Some(Box::new(inner)) })); Defensive patterns
Strategy: validation
Validate before calling
// before sending SkipConfirm over IPC
let Some(skip) = action.action_type.as_ref().and_then(|t| match t {
ActionType::SkipConfirm(s) => Some(s),
_ => None,
}) else { /* not this action */ };
if skip.action.is_none() {
anyhow::bail!("SkipConfirm requires a nested action");
} Type guard
fn skip_confirm_is_valid(s: &SkipConfirmAction) -> bool {
s.action.is_some()
} Try / catch
match protobuf_action.try_into() {
Ok(action) => dispatch(action),
Err(e) if e.to_string().contains("SkipConfirm missing action") => {
log::warn!("dropping malformed SkipConfirm action from IPC"); // keep server alive
},
Err(e) => return Err(e.context("action conversion failed")),
} Prevention
- Never default-construct protobuf actions; always set required submessages explicitly
- Generate client stubs from the same zellij commit/version as the server
- Add a validation pass over outbound action payloads in test builds
- Remember proto3 does not enforce required fields — presence checks are on you
When it happens
Trigger: An IPC client (CLI, plugin, or hand-rolled protobuf sender) emits Action { SkipConfirm {} } with no nested action — e.g. building the protobuf message with all-default fields. The CLI itself always sets it, so this typically comes from custom clients or version-skewed senders using stale generated stubs.
Common situations: Scripts/SDKs constructing protobuf actions manually; client built against an older proto schema where SkipConfirm had no inner action; partially-populated payloads after refactors; fuzzing or malformed-message testing.
Related errors
- NewTiledPluginPane missing plugin
- NewFloatingPluginPane missing plugin
- NewInPlacePluginPane missing plugin
- StartOrReloadPlugin missing plugin
- ChangeFloatingPaneCoordinates missing pane_id
AI-assisted analysis of zellij-org/zellij@98a0837077 (2026-08-16).
Data as JSON: /api/errors/5e95fe86de6e1d79.
Report an issue: GitHub.