pola-rs/polars · error

NAMED AGG NOT FOUND

Error message

NAMED AGG NOT FOUND

What it means

After the named-serde registry is installed, each named anonymous aggregation is resolved by (name, payload). This expect fires when the registry is set but get_agg() returns Ok(None) — the receiving process's registry simply has no entry for that name, meaning the producer's UDF is unknown to the consumer.

Source

Thrown at crates/polars-plan/src/dsl/expr/anonymous/agg.rs:39

    pub fn materialize(&self) -> PolarsResult<SpecialEq<Arc<dyn AnonymousAgg>>> {
        match self {
            Self::Deserialized(t) => Ok(t.clone()),
            Self::Named {
                name,
                payload,
                value,
            } => feature_gated!("serde", {
                use super::named_serde::NAMED_SERDE_REGISTRY_EXPR;
                match value {
                    Some(v) => Ok(v.clone()),
                    None => Ok(SpecialEq::new(
                        NAMED_SERDE_REGISTRY_EXPR
                            .read()
                            .unwrap()
                            .as_ref()
                            .expect("NAMED EXPR REGISTRY NOT SET")
                            .get_agg(name, payload.as_ref().unwrap())?
                            .expect("NAMED AGG NOT FOUND"),
                    )),
                }
            }),
            Self::Bytes(_b) => {
                feature_gated!("serde", {
                    use crate::dsl::anonymous::serde_expr;
                    serde_expr::deserialize_anon_agg(_b.as_ref()).map(SpecialEq::new)
                })
            },
        }
    }
}

impl Hash for OpaqueStreamingAgg {
    fn hash<H: Hasher>(&self, state: &mut H) {
        core::mem::discriminant(self).hash(state);
        match self {
            Self::Deserialized(ptr) => ptr.hash(state),

View on GitHub (pinned to df599052da)

Solutions

  1. Register an ExprRegistry on the consumer that implements get_agg for every name the producer can emit
  2. Align polars/plugin versions across all processes that exchange serialized plans
  3. When introducing a UDF name, add it to every registry before deploying producers that use it
  4. If the UDF is unavailable by design, send the cached value variant or a plain expression instead of the named form

Example fix

// before: registry set, but name unknown -> panic 'NAMED AGG NOT FOUND'

// after: registry that knows the producer's names
struct Reg;
impl ExprRegistry for Reg {
    fn get_agg(&self, name: &str, payload: &[u8]) -> PolarsResult<Option<Arc<dyn AnonymousAgg>>> {
        match name {
            "my_sum" => Ok(Some(Arc::new(MySum::decode(payload)))),
            _ => Ok(None),
        }
    }
}
set_named_serde_registry(Arc::new(Reg) as _);
Defensive patterns

Strategy: validation

Validate before calling

// registry contract test: every name the producer emits resolves
for name in producer_agg_names() {
    assert!(registry.get_agg(name, &[]).unwrap().is_some(), "unknown agg {name}");
}

Try / catch

std::panic::catch_unwind(|| deserialize(bytes))
    .map_err(|_| format!("named agg not registered on this node"))

Prevention

When it happens

Trigger: Deserializing a plan whose named agg (e.g. a custom aggregation registered by an extension) was produced by a different build/plugin that registered different names; version skew between producer and consumer registries.

Common situations: Rolling upgrades where nodes run different plugin versions, a renamed/removed UDF between releases, deserializing on a machine without the extension that owns the UDF.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/6a11630eb714d046. Report an issue: GitHub.