influxdata/influxdb · error

should have gotten a DictionaryArray

Error message

should have gotten a DictionaryArray

What it means

expect("should have gotten a DictionaryArray") panic in get_tag_identity_key: the guard already matched DataType::Dictionary(Int32, Utf8) on the column's logical type, so the code assumes as_any().downcast_ref::<DictionaryArray<Int32Type>>() must succeed. It panics when the physical array is not actually an Int32-keyed DictionaryArray despite the reported datatype.

Solutions

  1. Verify the actual arrow array key type matches Int32 before downcasting (check dict.key_type())
  2. Use downcast_ref and map the None case to a Result/None instead of expect()
  3. Align the schema DataType with the physical array: rebuild the dictionary with DictionaryArray::<Int32Type>
  4. Check the arrow-rs version; dictionary key inference defaults changed across versions

Example fix

// before
.expect("should have gotten a DictionaryArray")
// after
.ok_or_else(|| TimeColumnError::UnexpectedType("DictionaryArray<Int32>".into()))?
Defensive patterns

Strategy: type-guard

Validate before calling

// rust
let key_is_i32 = matches!(col.data_type(), DataType::Dictionary(k, _) if **k == DataType::Int32);

Type guard

// rust
fn as_i32_dict<'a>(a: &'a dyn Array) -> Option<&'a DictionaryArray<Int32Type>> {
    a.as_any().downcast_ref::<DictionaryArray<Int32Type>>()
}

Try / catch

let dict = col.as_any().downcast_ref::<DictionaryArray<Int32Type>>()
    .ok_or(TimeColumnError::UnexpectedType("expected Int32 dictionary"))?;

Prevention

When it happens

Trigger: Calling get_tag_identity_key on a tag column whose DataType reports Dictionary(Int32, Utf8) but whose underlying Arc<dyn Array> is a differently keyed dictionary (e.g. Int8/Int16/UInt keys) or a non-dictionary array due to a mislabeled field/schema.

Common situations: Arrow/upstream producers emitting dictionaries with non-Int32 keys while the schema claims Int32, or hand-built test arrays with mismatched key types, or an arrow-rs version change in dictionary key defaults.

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 influxdata/influxdb@06200ef96b (2026-09-19). Data as JSON: /api/errors/62717a3851b4be1b. Report an issue: GitHub.

Appendix: source

Thrown at core/partition/src/traits/record_batch.rs:30

    fn is_valid(&self, idx: usize) -> bool {
        Array::is_valid(&self, idx)
    }

    fn get_tag_identity_key(&self, idx: usize) -> Option<&Self::TagIdentityKey> {
        debug_assert!(PartitioningColumn::is_valid(self, idx));
        match self.data_type() {
            DataType::Utf8 => self
                .as_any()
                .downcast_ref::<StringArray>()
                .map(|col_data| col_data.value(idx)),
            DataType::Dictionary(key, value)
                if key.as_ref() == &DataType::Int32 && value.as_ref() == &DataType::Utf8 =>
            {
                let dict = self
                    .as_any()
                    .downcast_ref::<DictionaryArray<Int32Type>>()
                    .expect("should have gotten a DictionaryArray");

                let values = dict
                    .values()
                    .as_any()
                    .downcast_ref::<StringArray>()
                    .expect("should have gotten a StringArray");
                Some(values.value(dict.key(idx)?))
            }
            _ => None,
        }
    }

    fn get_tag_value<'a>(&'a self, tag_identity_key: &'a Self::TagIdentityKey) -> Option<&'a str> {
        Some(tag_identity_key)
    }

    fn type_description(&self) -> String {
        self.data_type().to_string()

View on GitHub (pinned to 06200ef96b)