databendlabs/databend · error

_ => unreachable!()

Error message

_ => unreachable!()

What it means

The build transform's process() matches on its Step enum to drive the pipeline state machine. The catch-all arm panics, meaning a Step variant (e.g. a synchronous step not expected in process, or a wrongly-set step) reached the synchronous processing path. This is an internal state-machine invariant: only specific steps are valid for synchronous processing.

Solutions

  1. Add a match arm for the unexpected Step variant in process(), or route it to the correct handler
  2. Log the actual step value in the panic message to accelerate diagnosis
  3. Audit all Step/AsyncStep variants and confirm each is handled in exactly the right phase
  4. Check recent changes to the build transform state machine

Example fix

// before
_ => unreachable!(),
// after
other => unreachable!("TransformHashJoinBuild::process got unexpected step: {:?}", other),
Defensive patterns

Strategy: validation

Validate before calling

// Assert the step is valid for synchronous processing before calling process()
match &self.step {
    Step::NeedInput | Step::Consume => {},
    other => return Err(ErrorCode::Internal(format!("invalid step for process(): {:?}", other))),
}

Type guard

fn sync_step(s: &Step) -> bool {
    matches!(s, Step::NeedInput | Step::Consume | Step::Sync(_))
}

Prevention

When it happens

Trigger: The transform's step field holds a Step value that process() does not explicitly handle (e.g. an async-only step, or a stale step left after a state transition bug).

Common situations: Regressions after adding new AsyncStep/Step variants without updating process(); pipeline scheduling anomalies where event()/process()/async_process() interleave unexpectedly.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11). Data as JSON: /api/errors/0bde365fec5950eb. Report an issue: GitHub.

Appendix: source

Thrown at src/query/service/src/pipelines/processors/transforms/hash_join/transform_hash_join_build.rs:283

                            if let Some(builder) = self.runtime_filter_builder.as_mut() {
                                builder.add_block(data_block)?;
                            }
                        }
                    }
                }
                self.data_blocks.clear();
                self.is_collect_finished = true;
                self.build_state.collect_done()
            }
            Step::Sync(SyncStep::Finalize) => {
                if let Some(task) = self.build_state.finalize_task() {
                    self.build_state.finalize(task)
                } else {
                    self.is_finalize_finished = true;
                    self.build_state.finalize_done(self.hash_table_type)
                }
            }
            _ => unreachable!(),
        }
    }

    #[async_backtrace::framed]
    async fn async_process(&mut self) -> Result<()> {
        match &self.step {
            Step::Async(AsyncStep::CheckSpillHappen) => {
                self.build_state.barrier.wait().await;
                self.is_spill_happen_checked = true;
                self.is_spill_happened = self
                    .build_state
                    .hash_join_state
                    .is_spill_happened
                    .load(Ordering::Acquire);
            }
            Step::Async(AsyncStep::WaitCollect) => {
                if let Some(builder) = self.runtime_filter_builder.take() {
                    let spill = self

View on GitHub (pinned to 288d84d76e)