{"record":{"id":"54f5a1e114adaac5","repo":"risingwavelabs/risingwave","slug":"multiple-udf-implementations-found-for-language","errorCode":null,"errorMessage":"multiple UDF implementations found for language: {language}","messagePattern":"multiple UDF implementations found for language: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/expr/core/src/sig/udf.rs","lineNumber":52,"sourceCode":"/// static MY_UDF_LANGUAGE: UdfImplDescriptor = UdfImplDescriptor {...};\n/// ```\n#[linkme::distributed_slice]\npub static UDF_IMPLS: [UdfImplDescriptor];\n\n/// Find a UDF implementation by language.\npub fn find_udf_impl(\n    language: &str,\n    runtime: Option<&str>,\n    link: Option<&str>,\n) -> Result<&'static UdfImplDescriptor> {\n    let mut impls = UDF_IMPLS\n        .iter()\n        .filter(|desc| (desc.match_fn)(language, runtime, link));\n    let impl_ = impls.next().context(\n        \"language not found.\\nHINT: UDF feature flag may not be enabled during compilation\",\n    )?;\n    if impls.next().is_some() {\n        bail!(\"multiple UDF implementations found for language: {language}\");\n    }\n    Ok(impl_)\n}\n\n/// UDF implementation descriptor.\n///\n/// Every UDF implementation should provide 3 functions:\npub struct UdfImplDescriptor {\n    /// Returns if a function matches the implementation.\n    ///\n    /// This function is used to determine which implementation to use for a UDF.\n    pub match_fn: fn(language: &str, runtime: Option<&str>, link: Option<&str>) -> bool,\n\n    /// Creates a function from options.\n    ///\n    /// This function will be called when `create function` statement is executed on the frontend.\n    pub create_fn: fn(opts: CreateOptions<'_>) -> Result<CreateFunctionOutput>,\n","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/expr/core/src/sig/udf.rs#L34-L70","documentation":"find_udf_impl resolves the concrete UDF implementation for a given language by filtering registered implementation descriptors with the match_fn. If more than one descriptor matches the same language/runtime/link combination, resolution is ambiguous and it bails — implementations must be uniquely selected.","triggerScenarios":"Calling find_udf_impl when two or more registered UdfImplDecriptors match the same language (e.g. two 'python' implementations registered due to duplicate feature-flag-gated registrations or a bug in a match_fn that is too permissive).","commonSituations":"Compiling with conflicting UDF feature flags that each register a 'python' (or other language) runtime; adding a new UDF implementation without narrowing its match_fn; duplicate registration of the same implementation.","solutions":["Check enabled cargo features — disable the overlapping/duplicate UDF feature flags","Fix the duplicate implementation's match_fn so only one matches a given (language, runtime, link)","Remove the redundant UdfImplDescriptor registration","Rebuild and confirm only one implementation matches each language"],"exampleFix":"// before: two impls both match \"python\"\n(desc: |lang, _, _| lang == \"python\") x2\n// after: disambiguate\n(desc: |lang, runtime, _| lang == \"python\" && runtime == EmbeddedRuntime::Pyo3)","handlingStrategy":"try-catch","validationCode":"// Count matching impls before resolution\nlet n = UDF_IMPLEMENTS.iter().filter(|d| (d.match_fn)(lang, rt, link)).count();\nassert!(n <= 1, \"ambiguous UDF impl for {lang}\");","typeGuard":null,"tryCatchPattern":"match find_udf_impl(lang, rt, link) { Err(e) if e.to_string().contains(\"multiple UDF implementations\") => disable_conflicting_feature(&e), Ok(i) => i, Err(e) => return Err(e) }","preventionTips":["Enable only one UDF runtime feature per language in Cargo features","Make each descriptor's match_fn mutually exclusive","Add a startup assertion that no two descriptors overlap"],"tags":["rust","udf","feature-flags","ambiguous-resolution"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}