{"record":{"id":"ea0c328b60c242f0","repo":"apache/beam","slug":"found-multiple-definitions-of-scalar-function-functionname","errorCode":null,"errorMessage":"Found multiple definitions of scalar function ${functionName} in ${jarPath}.","messagePattern":"Found multiple definitions of scalar function (.+?) in (.+?)\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/JavaUdfLoader.java","lineNumber":224,"sourceCode":"      LOG.debug(\"Using cached function definitions from {}\", jarPath);\n      return functionCache.get(jarPath);\n    }\n\n    ClassLoader classLoader = createClassLoader(jarPath);\n    Map<List<String>, ScalarFn> scalarFunctions = new HashMap<>();\n    Map<List<String>, AggregateFn> aggregateFunctions = new HashMap<>();\n    Iterator<UdfProvider> providers = getUdfProviders(classLoader);\n    int providersCount = 0;\n    while (providers.hasNext()) {\n      providersCount++;\n      UdfProvider provider = providers.next();\n      provider\n          .userDefinedScalarFunctions()\n          .forEach(\n              (functionName, implementation) -> {\n                List<String> functionPath = ImmutableList.copyOf(functionName.split(\"\\\\.\"));\n                if (scalarFunctions.containsKey(functionPath)) {\n                  throw new IllegalArgumentException(\n                      String.format(\n                          \"Found multiple definitions of scalar function %s in %s.\",\n                          functionName, jarPath));\n                }\n                scalarFunctions.put(functionPath, implementation);\n              });\n      provider\n          .userDefinedAggregateFunctions()\n          .forEach(\n              (functionName, implementation) -> {\n                List<String> functionPath = ImmutableList.copyOf(functionName.split(\"\\\\.\"));\n                if (aggregateFunctions.containsKey(functionPath)) {\n                  throw new IllegalArgumentException(\n                      String.format(\n                          \"Found multiple definitions of aggregate function %s in %s.\",\n                          functionName, jarPath));\n                }\n                aggregateFunctions.put(functionPath, implementation);","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/JavaUdfLoader.java#L206-L242","documentation":"JavaUdfLoader.loadJar() throws IllegalArgumentException when a UdfProvider in the jar registers two scalar functions whose names resolve to the same function path (split on '.'). The loader treats function paths as unique map keys, so duplicate registration is rejected rather than silently overwritten. This detects conflicting definitions shipped in the same jar.","triggerScenarios":"loadJar scanning a jar where userDefinedScalarFunctions() returns two entries mapping to the same List<String> path (e.g. the same fully-qualified name registered twice, or names colliding after '.' splitting).","commonSituations":"Accidentally registering the same function name twice in the provider map; merging two UDF libraries into one jar where both define the same fully-qualified function name; copy-paste duplication in the provider class.","solutions":["Remove or rename the duplicate entry in userDefinedScalarFunctions().","Use distinct fully-qualified names (different package or name) for colliding functions.","Rebuild the jar after de-duplicating and redeploy.","When merging libraries, namespace one under a different package."],"exampleFix":"// before\nreturn ImmutableMap.of(\"my.fn\", fnA, \"my.fn\", fnB);\n// after\nreturn ImmutableMap.of(\"my.fn\", fnA, \"my.otherFn\", fnB);","handlingStrategy":"try-catch","validationCode":"// detect duplicate registration in your own provider before packaging\nSet<List<String>> seen = new HashSet<>();\nfor (String name : providerMap.keySet()) {\n  if (!seen.add(ImmutableList.copyOf(name.split(\"\\\\.\")))) {\n    throw new IllegalStateException(\"Duplicate scalar fn: \" + name);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  udfLoader.loadScalarFunction(fnPath, jarPath);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"Found multiple definitions of scalar function\")) {\n    LOG.error(\"Duplicate UDF registration in jar {}: {}\", jarPath, e.getMessage());\n  }\n  throw e;\n}","preventionTips":["Never register the same fully-qualified function name twice","When merging UDF libraries, rename colliding functions","Add a build-time test that loads the jar and expects no duplicates","Use constants for function names instead of string literals"],"tags":["udf","duplicate","beam"],"backgroundTag":"conflicting-config-options","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}