databendlabs/databend · error
HashJoinHashTable::NestedLoop(_) => unreachable!()
Error message
HashJoinHashTable::NestedLoop(_) => unreachable!()
What it means
When finalizing a hash join build, the code dispatches on the HashJoinHashTable enum. The NestedLoop variant represents a join executed as a nested loop (no hash table), which should never reach the hash-table build/finalize path. Reaching this arm means the pipeline selected a nested-loop join but then attempted hash-table build finalization — an internal scheduling/type dispatch bug, so the code panics.
Solutions
- Check why the plan chose NestedLoop while a hash build transform was instantiated; align join strategy selection with the build transform
- Guard finalize to no-op or return an error for NestedLoop instead of panicking
- Reproduce with the failing query's EXPLAIN output and check join type/hints
- Upgrade or patch to a version where strategy negotiation is fixed
Example fix
// before HashJoinHashTable::NestedLoop(_) => unreachable!(), // after HashJoinHashTable::NestedLoop(_) => Ok(()), // nested loop join has no hash table to finalize
Defensive patterns
Strategy: validation
Validate before calling
// Before creating the build transform, verify the table type is hash-based
if matches!(hash_table_type, HashJoinHashTable::NestedLoop(_)) {
return Err(ErrorCode::Internal("nested loop join must not use hash build pipeline"));
} Type guard
fn is_hash_join_table(t: &HashJoinHashTable) -> bool {
!matches!(t, HashJoinHashTable::NestedLoop(_))
} Prevention
- Keep join strategy selection and transform construction in one place to avoid mismatch
- Add tests for cross joins and non-equi joins asserting they never instantiate the hash build path
- Return ErrorCode::Unimplemented instead of unreachable! for cross-strategy dispatch
When it happens
Trigger: finalize is called on a build state whose hash table type is NestedLoop. This happens if join strategy selection (hash vs nested loop) and the build transform's expectations disagree, e.g. after plan rewrites, cross joins, or join hints forcing a strategy mismatch.
Common situations: Queries with cross joins or inequality-only conditions that get planned as nested loops; misconfigured join hints; code changes to the hash table type negotiation between planner and executor.
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
- _ => unreachable!()
- HashJoinHashTable::NestedLoop(_) => unreachable!()
- _ => unreachable!()
- _ => unreachable!()
- Hash Table is finished
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/cffe6656e5f04201.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/service/src/pipelines/processors/transforms/hash_join/hash_join_build_state.rs:775
},
HashJoinHashTable::KeysU32(table) => insert_key! {
&mut table.hash_table, &table.hash_method, chunk, build_keys, valids, chunk_index as u32, entry_size, &mut local_raw_entry_spaces, u32,
},
HashJoinHashTable::KeysU64(table) => insert_key! {
&mut table.hash_table, &table.hash_method, chunk, build_keys, valids, chunk_index as u32, entry_size, &mut local_raw_entry_spaces, u64,
},
HashJoinHashTable::KeysU128(table) => insert_key! {
&mut table.hash_table, &table.hash_method, chunk, build_keys, valids, chunk_index as u32, entry_size, &mut local_raw_entry_spaces, u128,
},
HashJoinHashTable::KeysU256(table) => insert_key! {
&mut table.hash_table, &table.hash_method, chunk, build_keys, valids, chunk_index as u32, entry_size, &mut local_raw_entry_spaces, U256,
},
HashJoinHashTable::Null => {
return Err(ErrorCode::AbortedQuery(
"Aborted query, because the hash table is uninitialized.",
));
}
HashJoinHashTable::NestedLoop(_) => unreachable!(),
HashJoinHashTable::UniqueSerializer(table) => insert_binary_key! {
&mut table.hash_table, &table.hash_method, chunk, build_keys, valids, chunk_index as u32, entry_size, &mut local_raw_entry_spaces,
},
HashJoinHashTable::UniqueSingleBinary(table) => insert_binary_key! {
&mut table.hash_table, &table.hash_method, chunk, build_keys, valids, chunk_index as u32, entry_size, &mut local_raw_entry_spaces,
},
HashJoinHashTable::UniqueKeysU8(table) => insert_key! {
&mut table.hash_table, &table.hash_method, chunk, build_keys, valids, chunk_index as u32, entry_size, &mut local_raw_entry_spaces, u8,
},
HashJoinHashTable::UniqueKeysU16(table) => insert_key! {
&mut table.hash_table, &table.hash_method, chunk, build_keys, valids, chunk_index as u32, entry_size, &mut local_raw_entry_spaces, u16,
},
HashJoinHashTable::UniqueKeysU32(table) => insert_key! {
&mut table.hash_table, &table.hash_method, chunk, build_keys, valids, chunk_index as u32, entry_size, &mut local_raw_entry_spaces, u32,
},
HashJoinHashTable::UniqueKeysU64(table) => insert_key! {
&mut table.hash_table, &table.hash_method, chunk, build_keys, valids, chunk_index as u32, entry_size, &mut local_raw_entry_spaces, u64,
},View on GitHub (pinned to 288d84d76e)