quickwit-oss/quickwit · error

dictionary downcast failed for

Error message

dictionary downcast failed for {:?}

What it means

extract_string_value supports only Dictionary(Int32, Utf8) arrays for string tag columns. When the Arrow array's data type is a dictionary, it attempts a downcast to DictionaryArray<Int32Type>; if the keys are not Int32 (e.g. UInt8/UInt16 dictionary from a different parquet writer), the downcast returns None and this error is raised.

Solutions

  1. Check the parquet writer settings that choose the dictionary index type and force Int32 keys
  2. Normalize the array before calling (e.g. cast dictionary keys to Int32 via arrow::compute::cast)
  3. Widen extract_string_value to handle other dictionary key widths
  4. Inspect array.data_type() in the error message to see the actual key type

Example fix

// before
let dict = array.as_any().downcast_ref::<DictionaryArray<Int32Type>>().ok_or_else(...)?;
// after: normalize non-Int32 dictionaries first
let array = match array.data_type() {
    DataType::Dictionary(k, _) if **k != DataType::Int32 => arrow::compute::cast(array, &DataType::Dictionary(DataType::Int32.into(), DataType::Utf8.into()))?,
    _ => array.clone(),
};
Defensive patterns

Strategy: type-guard

Validate before calling

if let DataType::Dictionary(k, v) = array.data_type() {
    if **k != DataType::Int32 || **v != DataType::Utf8 { /* normalize via cast */ }
}

Type guard

fn is_int32_utf8_dict(array: &dyn Array) -> bool {
    matches!(array.data_type(), DataType::Dictionary(k, v) if **k == DataType::Int32 && **v == DataType::Utf8)
}

Try / catch

match encode_row_key(...) {
    Err(e) if e.to_string().contains("dictionary downcast failed") => {
        let arr = arrow::compute::cast(array, &DataType::Utf8)?; /* retry */
    }
    Err(e) => return Err(e),
    Ok(v) => v,
}

Prevention

When it happens

Trigger: encode_row_key hits a tag column whose Arrow array is DataType::Dictionary(_, _) but with a non-Int32 key type — downcast_ref::<DictionaryArray<Int32Type>>() returns None.

Common situations: Reading parquet files written with dictionary-encoded strings using smaller key widths (UInt8/UInt16/UInt64), or files produced by tools that pick a different dictionary index type based on cardinality.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/30f1610b0eb40a18. Report an issue: GitHub.

Appendix: source

Thrown at quickwit/quickwit-parquet-engine/src/sorted_series/mod.rs:327

}

/// Extract a string value from a column at the given row.
///
/// Supports `Dictionary(Int32, Utf8)` (the common tag encoding) and
/// plain `Utf8` columns. Returns an error for unsupported types — tag
/// columns in the sort schema must be string-typed.
fn extract_string_value(array: &dyn Array, row: usize) -> Result<&str> {
    debug_assert!(
        !array.is_null(row),
        "caller must check is_null before extract_string_value"
    );

    match array.data_type() {
        DataType::Dictionary(_, _) => {
            let dict = array
                .as_any()
                .downcast_ref::<DictionaryArray<Int32Type>>()
                .ok_or_else(|| anyhow!("dictionary downcast failed for {:?}", array.data_type()))?;
            let key_idx = dict.keys().value(row) as usize;
            let values = dict.values();
            let str_values = values
                .as_any()
                .downcast_ref::<StringArray>()
                .ok_or_else(|| anyhow!("dictionary values are not Utf8"))?;
            Ok(str_values.value(key_idx))
        }
        DataType::Utf8 => {
            let arr = array
                .as_any()
                .downcast_ref::<StringArray>()
                .ok_or_else(|| anyhow!("Utf8 downcast failed"))?;
            Ok(arr.value(row))
        }
        other => Err(anyhow!(
            "unsupported data type {:?} in sort schema tag column — only Dictionary(Int32, Utf8) \
             and Utf8 are supported",

View on GitHub (pinned to a39730c5cd)