influxdata/influxdb · error

should have gotten a StringArray

Error message

should have gotten a StringArray

What it means

expect("should have gotten a StringArray") panic in get_tag_identity_key: after successfully downcasting to DictionaryArray<Int32Type>, the code downcasts dict.values() to StringArray because the schema promised Utf8 dictionary values. If the dictionary's value array is not a StringArray (e.g. LargeStringArray or BinaryArray), the downcast returns None and expect panics.

Solutions

  1. Confirm the dictionary's values() array is a StringArray (Utf8) before downcasting
  2. Handle the None case gracefully: return None or map to an error instead of expect()
  3. Normalize ingestion so tag dictionaries always use Utf8 value arrays
  4. Add a schema check that rejects Dictionary types whose values are not Utf8

Example fix

// before
.expect("should have gotten a StringArray");
// after
.ok_or_else(|| TimeColumnError::UnexpectedType("StringArray".into()))?;
Defensive patterns

Strategy: type-guard

Validate before calling

// rust
fn dict_values_are_utf8(dict: &DictionaryArray<Int32Type>) -> bool {
    dict.values().as_any().downcast_ref::<StringArray>().is_some()
}

Type guard

// rust
fn as_string_values<'a>(dict: &'a DictionaryArray<Int32Type>) -> Option<&'a StringArray> {
    dict.values().as_any().downcast_ref::<StringArray>()
}

Try / catch

let values = dict.values().as_any().downcast_ref::<StringArray>()
    .ok_or(TimeColumnError::UnexpectedType("expected Utf8 dictionary values"))?;

Prevention

When it happens

Trigger: A dictionary column whose values are LargeUtf8/Binary/other rather than Utf8, while the schema-level DataType guard matched Dictionary(Int32, Utf8) — i.e. schema and physical value array disagree, or the guard is bypassed by a differently typed value array.

Common situations: Data written by a producer using LargeStringArray-backed dictionaries, arrow-rs upgrades changing default value types, or fixtures building dictionaries with non-string values.

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/cbaf0adffaccd1c0. Report an issue: GitHub.

Appendix: source

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

        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()
    }
}

impl Batch for RecordBatch {
    type Column = Arc<dyn Array>;

View on GitHub (pinned to 06200ef96b)