xai-org/x-algorithm · error · anyhow::Error
not StructArray
Error message
not StructArray
What it means
The elements of the user_actions list must be a StructArray (each action a struct with feature fields). After taking list.value(0), the code downcasts to StructArray; if the list's value type is not a struct (e.g. primitives or a nested list), this error is raised. It also guards against a 'zero actions' bail immediately after.
Source
Thrown at bdsm/rust/abuse-v3-features/src/lib.rs:273
arrow::compute::concat_batches(&batches[0].schema(), &batches)?
};
let actions_col = batch
.column_by_name("user_actions")
.ok_or_else(|| anyhow::anyhow!("no user_actions"))?;
let list = actions_col
.as_any()
.downcast_ref::<ListArray>()
.ok_or_else(|| anyhow::anyhow!("not ListArray"))?;
if list.is_empty() || list.is_null(0) {
anyhow::bail!("empty list");
}
let vals = list.value(0);
let sa = vals
.as_any()
.downcast_ref::<StructArray>()
.ok_or_else(|| anyhow::anyhow!("not StructArray"))?;
let total = sa.len();
if total == 0 {
anyhow::bail!("zero actions");
}
let start = if total > seq_len { total - seq_len } else { 0 };
let take = total.min(seq_len);
let sl = sa.slice(start, take);
let sl = sl.as_any().downcast_ref::<StructArray>().unwrap();
let n = take;
Ok(UserArrowFeatures {
n,
action_name: get_i32(sl, "action_name"),
tweet_id: get_i64(sl, "tweet_id"),
author_id: get_i64(sl, "author_id"),
engagement_time_ms: get_i64(sl, "engagement_time_ms"),
dwell_time: get_i32(sl, "dwell_time"),View on GitHub (pinned to 24c60942c5)
Solutions
- Inspect list.value_type() / the inner DataType and compare against the expected struct fields
- Fix the producer to emit list<struct<...>> with the agreed field set
- Update this consumer to handle the new inner type if the change is intentional
- Add a schema contract check (expected inner struct fields) before extraction runs
Example fix
// before
let sa = vals
.as_any()
.downcast_ref::<StructArray>()
.ok_or_else(|| anyhow::anyhow!("not StructArray"))?;
// after
let sa = vals
.as_any()
.downcast_ref::<StructArray>()
.ok_or_else(|| anyhow::anyhow!(
"not StructArray: inner type is {:?}",
vals.data_type()
))?; Defensive patterns
Strategy: type-guard
Validate before calling
// Validate inner element type before extraction
if let Some(col) = batch.column_by_name("user_actions") {
if let DataType::List(f) = col.data_type() {
anyhow::ensure!(matches!(f.data_type(), DataType::Struct(_)), "inner type must be struct");
}
} Type guard
fn actions_are_structs(list: &ListArray) -> bool {
matches!(list.value_type(), DataType::Struct(_))
} Try / catch
// verify inner type, then downcast safely
let vals = list.value(0);
let sa = vals.as_any().downcast_ref::<StructArray>()
.ok_or_else(|| anyhow::anyhow!("expected struct inner type, got {:?}", vals.data_type()))?; Prevention
- Share the exact struct field definitions between producer and consumer
- Add schema contract tests that run the extractor against a golden batch
- Fail fast on schema changes in CI with a schema-diff check
When it happens
Trigger: Calling extract_batch where the list's inner type is not Struct — producer changed the element type, or the actions structs were flattened/unnested upstream.
Common situations: Schema evolution of the action struct (fields added/removed and re-encoded differently), producers writing list<list<...>> or list<string> variants, or mismatched versions between the feature-generation job and this library.
Related errors
- not ListArray
- no user_actions
- function passed to Foldl() returns %s but seed value is a %s
- Foldl1 is expected to return %s but passed function returns
- Sort is expected to return %s but passed function returns %s
AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28).
Data as JSON: /api/errors/d8b3fde657159fe4.
Report an issue: GitHub.