{"record":{"id":"26d4e27753f3bf2f","repo":"pola-rs/polars","slug":"named-expr-registry-not-set-26d4e2","errorCode":null,"errorMessage":"NAMED EXPR REGISTRY NOT SET","messagePattern":"NAMED EXPR REGISTRY NOT SET","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/polars-plan/src/dsl/expr/anonymous/expr.rs","lineNumber":182,"sourceCode":"\nimpl OpaqueColumnUdf {\n    pub fn materialize(self) -> PolarsResult<SpecialEq<Arc<dyn AnonymousColumnsUdf>>> {\n        match self {\n            Self::Deserialized(t) => Ok(t),\n            Self::Named {\n                name,\n                payload,\n                value,\n            } => feature_gated!(\"serde\", {\n                use super::named_serde::NAMED_SERDE_REGISTRY_EXPR;\n                match value {\n                    Some(v) => Ok(v),\n                    None => Ok(SpecialEq(\n                        NAMED_SERDE_REGISTRY_EXPR\n                            .read()\n                            .unwrap()\n                            .as_ref()\n                            .expect(\"NAMED EXPR REGISTRY NOT SET\")\n                            .get_function(&name, payload.unwrap().as_ref())\n                            .expect(\"NAMED FUNCTION NOT FOUND\"),\n                    )),\n                }\n            }),\n            Self::Bytes(_b) => {\n                feature_gated!(\"serde\";\"python\", {\n                    serde_expr::deserialize_column_udf(_b.as_ref()).map(SpecialEq::new)\n                })\n            },\n        }\n    }\n}\n","sourceCodeStart":164,"sourceCodeEnd":196,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/crates/polars-plan/src/dsl/expr/anonymous/expr.rs#L164-L196","documentation":"Same named-serde mechanism as error 626 but for anonymous column UDFs: deserializing a named function variant requires the global NAMED_SERDE_REGISTRY_EXPR to have been installed via set_named_serde_registry. In a process that never registered it, the RwLock holds None and this expect panics during expression deserialization.","triggerScenarios":"Deserializing a serialized expression/plan containing a named anonymous function (e.g. a Python UDF serialized by name) in a fresh interpreter/process/subprocess that did not set the registry at startup.","commonSituations":"Multiprocessing or cluster workers receiving pickled/serialized lazy frames; long-lived daemons that deserialize plans created elsewhere; minimal embeddings and test binaries that skip the registry bootstrap.","solutions":["Call set_named_serde_registry(...) once per process before deserializing any expression","Use the registry-supporting entrypoint (e.g. the polars build that registers its UDFs on startup) rather than a bare polars_plan dependency","Serialize the cached value variant when the consumer cannot provide the registry","Pin identical polars/extension versions on producer and consumer"],"exampleFix":"// before: worker deserializes a plan with a named UDF -> panic\nlet lf: LazyFrame = bincode::deserialize(bytes)?;\n\n// after: register in every worker before deserialize\nset_named_serde_registry(Arc::new(WorkerUdfRegistry) as _);\nlet lf: LazyFrame = bincode::deserialize(bytes)?;","handlingStrategy":"validation","validationCode":"// every worker/subprocess calls this before deserializing expressions\nset_named_serde_registry(Arc::new(WorkerUdfRegistry) as _);","typeGuard":null,"tryCatchPattern":"let expr = std::panic::catch_unwind(|| serde_json::from_str::<Expr>(s))\n    .map_err(|_| anyhow!(\"named UDF registry not set in this process\"))?;","preventionTips":["Centralize registry setup in the process entrypoint","Deserializing in tests? register there too","Ship the registry installer with the plan format"],"tags":["serde","serialization","udf","registry","multiprocessing","panic","rust"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}