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

  1. Check why the plan chose NestedLoop while a hash build transform was instantiated; align join strategy selection with the build transform
  2. Guard finalize to no-op or return an error for NestedLoop instead of panicking
  3. Reproduce with the failing query's EXPLAIN output and check join type/hints
  4. 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

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


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)