{"record":{"id":"b7acf47249d1892f","repo":"databendlabs/databend","slug":"unreachable-b7acf4","errorCode":null,"errorMessage":"_ => unreachable!()","messagePattern":"_ => unreachable!\\(\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/query/service/src/pipelines/processors/transforms/hash_join/hash_join_probe_state.rs","lineNumber":437,"sourceCode":"        let tasks = (0..task_num).collect_vec();\n        *self.final_scan_tasks.write() = tasks.into();\n        Ok(())\n    }\n\n    pub fn final_scan_task(&self) -> Option<usize> {\n        let mut tasks = self.final_scan_tasks.write();\n        tasks.pop_front()\n    }\n\n    pub fn final_scan(&self, task: usize, state: &mut ProbeState) -> Result<Vec<DataBlock>> {\n        match &self.hash_join_state.hash_join_desc.join_type {\n            JoinType::Right | JoinType::RightAny | JoinType::RightSingle | JoinType::Full => {\n                self.right_and_full_outer_scan(task, state)\n            }\n            JoinType::RightSemi => self.right_semi_outer_scan(task, state),\n            JoinType::RightAnti => self.right_anti_outer_scan(task, state),\n            JoinType::LeftMark => self.left_mark_scan(task, state),\n            _ => unreachable!(),\n        }\n    }\n\n    pub fn right_and_full_outer_scan(\n        &self,\n        task: usize,\n        probe_state: &mut ProbeState,\n    ) -> Result<Vec<DataBlock>> {\n        check_interrupt()?;\n\n        // Probe states.\n        let max_block_size = probe_state.max_block_size;\n        let mutable_indexes = &mut probe_state.mutable_indexes;\n        let build_indexes = &mut mutable_indexes.build_indexes;\n        let mut projected_probe_fields = vec![];\n        for (i, field) in self.probe_schema.fields().iter().enumerate() {\n            if self.probe_projections.contains(&i) {\n                projected_probe_fields.push(field.clone());","sourceCodeStart":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/query/service/src/pipelines/processors/transforms/hash_join/hash_join_probe_state.rs#L419-L455","documentation":"final_scan dispatches on JoinType to run the appropriate final-scan (outer/anti/semi/mark) pass. The catch-all arm panics, so a JoinType that is not one of the explicitly handled variants reaching final_scan is an internal bug: only right-side/full/mark joins should require a final scan, and any other type here means the caller dispatched final scan for a join that doesn't need one.","triggerScenarios":"final_scan is called with task data for a join whose JoinType is Left, Inner, LeftSemi, LeftAnti, LeftAny, LeftSingle, etc. — i.e. the driver invoked final scan when no right-side scan was required, or a new JoinType was added without updating this match.","commonSituations":"Adding a new JoinType to the planner without updating hash_join_probe_state's final_scan; bugs in the condition deciding whether a final scan is needed (should_probe_final_scan-like checks).","solutions":["Add a match arm for the offending JoinType in final_scan, or fix the caller's condition that decides final scan is needed","Enumerate all JoinType variants and confirm which legitimately need final scan","Check recent commits adding join types for missed match arms","Reduce the failing query to its join type and file an issue with EXPLAIN output"],"exampleFix":"// before\n_ => unreachable!(),\n// after\nJoinType::LeftSemi | JoinType::LeftAnti => Ok(vec![]), // no right-side final scan needed\nother => Err(ErrorCode::Internal(format!(\"unexpected join type in final_scan: {:?}\", other))),","handlingStrategy":"validation","validationCode":"// Only invoke final_scan for join types that need a right-side scan\nfn needs_final_scan(jt: &JoinType) -> bool {\n    matches!(jt, JoinType::Right | JoinType::RightAny | JoinType::RightSingle\n        | JoinType::Full | JoinType::RightSemi | JoinType::RightAnti | JoinType::LeftMark)\n}\nif !needs_final_scan(&join_type) { skip_final_scan(); }","typeGuard":"fn needs_final_scan(jt: &JoinType) -> bool {\n    matches!(jt, JoinType::Right | JoinType::RightAny | JoinType::RightSingle\n        | JoinType::Full | JoinType::RightSemi | JoinType::RightAnti | JoinType::LeftMark)\n}","tryCatchPattern":null,"preventionTips":["When adding a JoinType, grep for exhaustive matches on JoinType and update all of them","Derive the final-scan requirement from the JoinType enum itself rather than ad-hoc caller checks","Add exhaustiveness tests enumerating every JoinType through the probe pipeline"],"tags":["rust","panic","hash-join","join-type"],"backgroundTag":"internal-invariant-violation","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}