apache/skywalking · error · IllegalArgumentException

Duplicate @MALContextFunction name '{}' in namespace '{}' fr

Error message

Duplicate @MALContextFunction name '{}' in namespace '{}' from {}

What it means

SPI validation error from MalExtensionRegistry: two methods annotated @MALContextFunction within the same MalFunctionExtension implementation share the same Java method name. Since MAL resolves calls as namespace::methodName and generated code is a plain static call by name, a namespace cannot export overloads — the second registration aborts with IllegalArgumentException.

Source

Thrown at oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/rt/MalExtensionRegistry.java:116

            final Type[] genericTypes = m.getGenericParameterTypes();
            for (int i = 1; i < genericTypes.length; i++) {
                if (List.class.isAssignableFrom(extraParamTypes[i - 1])
                        && genericTypes[i] instanceof ParameterizedType) {
                    final Type elementType =
                        ((ParameterizedType) genericTypes[i])
                            .getActualTypeArguments()[0];
                    if (!String.class.equals(elementType)) {
                        throw new IllegalArgumentException(
                            "@MALContextFunction " + ext.getClass().getSimpleName()
                                + "." + m.getName()
                                + "() List parameters must be List<String>, got "
                                + genericTypes[i]);
                    }
                }
            }
            final String methodName = m.getName();
            if (methods.containsKey(methodName)) {
                throw new IllegalArgumentException(
                    "Duplicate @MALContextFunction name '" + methodName
                        + "' in namespace '" + namespace
                        + "' from " + ext.getClass().getName());
            }
            final String fqcn = m.getDeclaringClass().getName();
            methods.put(methodName,
                        new ExtensionMethod(fqcn, methodName, extraParamTypes));
            log.info("Registered MAL extension function {}::{}() -> {}.{}()",
                     namespace, methodName, fqcn, methodName);
        }
        if (!methods.isEmpty()) {
            if (REGISTRY.containsKey(namespace)) {
                throw new IllegalArgumentException(
                    "Duplicate MAL extension namespace '" + namespace
                        + "' from " + ext.getClass().getName());
            }
            REGISTRY.put(namespace, methods);
        }

View on GitHub (pinned to 102af09b4a)

Solutions

  1. Give each variant a distinct method name, e.g. filter() and filterWithValue(String)
  2. Keep a single method with the full parameter list and let rules pass all arguments
  3. Split the functions into two namespaces (two MalFunctionExtension implementations with different name()) if the overloads are conceptually separate

Example fix

// before
@MALContextFunction public static SampleFamily f(SampleFamily sf) { ... }
@MALContextFunction public static SampleFamily f(SampleFamily sf, String k) { ... }

// after
@MALContextFunction public static SampleFamily f(SampleFamily sf) { ... }
@MALContextFunction public static SampleFamily fByKey(SampleFamily sf, String k) { ... }
Defensive patterns

Strategy: validation

Validate before calling

Set<String> seen = new HashSet<>();
for (Method m : ext.getClass().getMethods()) {
    if (m.isAnnotationPresent(MALContextFunction.class) && !seen.add(m.getName())) {
        throw new IllegalArgumentException("Overloaded @MALContextFunction " + m.getName());
    }
}

Try / catch

startup-time; rename the overloads and redeploy

Prevention

When it happens

Trigger: Defining 'f(SampleFamily)' and 'f(SampleFamily, String)' in the same extension class, both annotated. methods.containsKey(methodName) is true when the second one registers.

Common situations: Natural Java overloading instinct when adding a convenience variant of an existing extension function; merging two extension classes that both define a method with the same name into one namespace.

Related errors


AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14). Data as JSON: /api/errors/46ad81a80910cc03. Report an issue: GitHub.