{"record":{"id":"b25f17b39f9ef8b6","repo":"apache/skywalking","slug":"duplicate-mal-extension-namespace-from","errorCode":null,"errorMessage":"Duplicate MAL extension namespace '{}' from {}","messagePattern":"Duplicate MAL extension namespace '(.+?)' from (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/rt/MalExtensionRegistry.java","lineNumber":129,"sourceCode":"                    }\n                }\n            }\n            final String methodName = m.getName();\n            if (methods.containsKey(methodName)) {\n                throw new IllegalArgumentException(\n                    \"Duplicate @MALContextFunction name '\" + methodName\n                        + \"' in namespace '\" + namespace\n                        + \"' from \" + ext.getClass().getName());\n            }\n            final String fqcn = m.getDeclaringClass().getName();\n            methods.put(methodName,\n                        new ExtensionMethod(fqcn, methodName, extraParamTypes));\n            log.info(\"Registered MAL extension function {}::{}() -> {}.{}()\",\n                     namespace, methodName, fqcn, methodName);\n        }\n        if (!methods.isEmpty()) {\n            if (REGISTRY.containsKey(namespace)) {\n                throw new IllegalArgumentException(\n                    \"Duplicate MAL extension namespace '\" + namespace\n                        + \"' from \" + ext.getClass().getName());\n            }\n            REGISTRY.put(namespace, methods);\n        }\n    }\n\n    /**\n     * Look up an extension method at compile time for validation and codegen.\n     *\n     * @return the extension method descriptor, or null if not found\n     */\n    public static ExtensionMethod lookup(final String namespace,\n                                          final String methodName) {\n        final Map<String, ExtensionMethod> methods = REGISTRY.get(namespace);\n        if (methods == null) {\n            return null;\n        }","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/rt/MalExtensionRegistry.java#L111-L147","documentation":"SPI validation error from MalExtensionRegistry: two different MalFunctionExtension implementations report the same namespace via name(), and both export at least one @MALContextFunction method. Method names only need to be unique within a namespace, so a duplicate namespace would create ambiguity in ns::method resolution and in generated static calls — the second registration throws.","triggerScenarios":"Two jars each contain a class implementing MalFunctionExtension with name() returning e.g. \"genai\" and both have annotated methods; REGISTRY.containsKey(namespace) is true when the second one finishes scanning its methods.","commonSituations":"Deploying two versions of a custom extension jar into OAP's oap-libs/ext simultaneously; a fork and the original of the same extension both on the classpath; copy-pasting an extension class without changing name().","solutions":["Ensure only one jar providing a given namespace is on the classpath — remove old versions from ext/ or oap-libs","If both must coexist, rename one implementation's name() namespace and update rules accordingly","Check for duplicate SPI entries across jars: grep the META-INF/services files of all deployed extension jars"],"exampleFix":"# before: two jars both declare\npublic String name() { return \"genai\"; }\n\n# after: remove the stale jar, or rename one\npublic String name() { return \"genai2\"; }  # and update rules to genai2::...","handlingStrategy":"validation","validationCode":"// deployment check: ensure no two jars declare the same namespace\nSet<String> namespaces = new HashSet<>();\nfor (MalFunctionExtension e : ServiceLoader.load(MalFunctionExtension.class)) {\n    if (!namespaces.add(e.name())) {\n        throw new IllegalStateException(\"Duplicate MAL extension namespace: \" + e.name());\n    }\n}","typeGuard":null,"tryCatchPattern":"startup-time; remove the duplicate jar from the classpath (ext/, oap-libs) rather than catching","preventionTips":["Clean old extension jars out of ext/ on upgrade — stale duplicates are the usual cause","Namespace-name extension jars explicitly (e.g. myext-mal-ext-1.0.jar) and audit the services files across jars"],"tags":["mal","extension","spi","duplicate","classpath","startup"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}