risingwavelabs/risingwave · error

multiple UDF implementations found for language: {language}

Error message

multiple UDF implementations found for language: {language}

What it means

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.

Source

Thrown at src/expr/core/src/sig/udf.rs:52

/// static MY_UDF_LANGUAGE: UdfImplDescriptor = UdfImplDescriptor {...};
/// ```
#[linkme::distributed_slice]
pub static UDF_IMPLS: [UdfImplDescriptor];

/// Find a UDF implementation by language.
pub fn find_udf_impl(
    language: &str,
    runtime: Option<&str>,
    link: Option<&str>,
) -> Result<&'static UdfImplDescriptor> {
    let mut impls = UDF_IMPLS
        .iter()
        .filter(|desc| (desc.match_fn)(language, runtime, link));
    let impl_ = impls.next().context(
        "language not found.\nHINT: UDF feature flag may not be enabled during compilation",
    )?;
    if impls.next().is_some() {
        bail!("multiple UDF implementations found for language: {language}");
    }
    Ok(impl_)
}

/// UDF implementation descriptor.
///
/// Every UDF implementation should provide 3 functions:
pub struct UdfImplDescriptor {
    /// Returns if a function matches the implementation.
    ///
    /// This function is used to determine which implementation to use for a UDF.
    pub match_fn: fn(language: &str, runtime: Option<&str>, link: Option<&str>) -> bool,

    /// Creates a function from options.
    ///
    /// This function will be called when `create function` statement is executed on the frontend.
    pub create_fn: fn(opts: CreateOptions<'_>) -> Result<CreateFunctionOutput>,

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Check enabled cargo features — disable the overlapping/duplicate UDF feature flags
  2. Fix the duplicate implementation's match_fn so only one matches a given (language, runtime, link)
  3. Remove the redundant UdfImplDescriptor registration
  4. Rebuild and confirm only one implementation matches each language

Example fix

// before: two impls both match "python"
(desc: |lang, _, _| lang == "python") x2
// after: disambiguate
(desc: |lang, runtime, _| lang == "python" && runtime == EmbeddedRuntime::Pyo3)
Defensive patterns

Strategy: try-catch

Validate before calling

// Count matching impls before resolution
let n = UDF_IMPLEMENTS.iter().filter(|d| (d.match_fn)(lang, rt, link)).count();
assert!(n <= 1, "ambiguous UDF impl for {lang}");

Try / catch

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

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/54f5a1e114adaac5. Report an issue: GitHub.