{"record":{"id":"7aa2e38721fa18fe","repo":"databendlabs/databend","slug":"hash-table-is-finished","errorCode":null,"errorMessage":"Hash Table is finished","messagePattern":"Hash Table is finished","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/query/service/src/pipelines/processors/transforms/hash_join/transform_hash_join_probe.rs","lineNumber":294,"sourceCode":"        }\n\n        self.next_round()\n    }\n\n    fn wait_build(&mut self) -> Result<Event> {\n        if self.is_build_finished() {\n            match self.hash_table_type {\n                HashTableType::FirstRound => self.probe(),\n                HashTableType::Restored => self.next_step(Step::Async(AsyncStep::Restore)),\n                HashTableType::Empty => {\n                    if self.can_fast_return() {\n                        self.next_step(Step::Finish)\n                    } else {\n                        self.probe()\n                    }\n                }\n                HashTableType::UnFinished => {\n                    unreachable!(\"Hash Table is finished\")\n                }\n            }\n        } else {\n            self.next_step(Step::Async(AsyncStep::WaitBuild))\n        }\n    }\n}\n\n#[async_trait::async_trait]\nimpl Processor for TransformHashJoinProbe {\n    fn name(&self) -> String {\n        \"HashJoinProbe\".to_string()\n    }\n\n    fn as_any(&mut self) -> &mut dyn Any {\n        self\n    }\n","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/query/service/src/pipelines/processors/transforms/hash_join/transform_hash_join_probe.rs#L276-L312","documentation":"In the probe transform's wait_build, the hash table status is checked; HashTableType::UnFinished inside a branch that only runs after the build has finished is asserted to be impossible, so it panics with 'Hash Table is finished'. Hitting it means the probe observed a table state inconsistent with the barrier/synchronization that should guarantee the build completed — an internal synchronization invariant violation.","triggerScenarios":"wait_build proceeds after deciding the build is done, but the shared table type still reports UnFinished; caused by a race between build finalization and probe reads, or incorrect status updates in finalize_done.","commonSituations":"Distributed/multi-threaded builds where barriers fail or partial builds abort; hangs or errors during build (e.g. aborted query) leaving the status stale; regressions in build-probe synchronization code.","solutions":["Check whether the build phase aborted or errored before finalize_done updated the table type; surface that original error instead of panicking","Verify the status transition to Finished happens under the same synchronization that unblocks waiters","Add the actual HashTableType value to the panic message for diagnosis","If triggered by an aborted build, ensure probes observe the failure and return AbortedQuery rather than waiting"],"exampleFix":"// before\nHashTableType::UnFinished => {\n    unreachable!(\"Hash Table is finished\")\n}\n// after\nHashTableType::UnFinished => Err(ErrorCode::AbortedQuery(\n    \"Aborted query, because the hash table build did not finish\",\n)),","handlingStrategy":"try-catch","validationCode":"// Before waiting, confirm the build will finalize or abort cleanly\nif build_aborted.load(Ordering::Acquire) {\n    return Err(ErrorCode::AbortedQuery(\"hash table build aborted\"));\n}","typeGuard":"fn build_finished(t: &HashTableType) -> bool {\n    !matches!(t, HashTableType::UnFinished)\n}","tryCatchPattern":"match wait_build_result {\n    Err(e) if e.code() == ErrorCode::ABORTED_QUERY => { log::warn!(\"build aborted: {}\", e); propagate_abort(); }\n    other => other,\n}","preventionTips":["Ensure build failures/aborts always update the shared table status before unblocking probes","Use the barrier/finalize_done path consistently; never leave UnFinished reachable after waiters wake","Keep build and probe on identical versions in distributed deployments"],"tags":["rust","panic","hash-join","synchronization","race-condition"],"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"}