{"record":{"id":"2e0b7012037e5d7c","repo":"apache/maven","slug":"unsupported-class-loading-strategy-supported","errorCode":null,"errorMessage":"Unsupported class-loading strategy '{}'. Supported values are: parent-first, plugin and self-first","messagePattern":"Unsupported class-loading strategy '(.+?)'\\. Supported values are: parent-first, plugin and self-first","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"compat/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java","lineNumber":185,"sourceCode":"\n        return Collections.unmodifiableList(extensions);\n    }\n\n    private CoreExtensionEntry createExtension(CoreExtension extension, List<Artifact> artifacts) throws Exception {\n        String realmId = \"coreExtension>\" + extension.getGroupId() + \":\" + extension.getArtifactId() + \":\"\n                + extension.getVersion();\n        final ClassRealm realm = classWorld.newRealm(realmId, null);\n        Set<String> providedArtifacts = Collections.emptySet();\n        String classLoadingStrategy = extension.getClassLoadingStrategy();\n        if (STRATEGY_PARENT_FIRST.equals(classLoadingStrategy)) {\n            realm.importFrom(parentRealm, \"\");\n        } else if (STRATEGY_PLUGIN.equals(classLoadingStrategy)) {\n            coreExports.getExportedPackages().forEach((p, cl) -> realm.importFrom(cl, p));\n            providedArtifacts = coreExports.getExportedArtifacts();\n        } else if (STRATEGY_SELF_FIRST.equals(classLoadingStrategy)) {\n            realm.setParentRealm(parentRealm);\n        } else {\n            throw new IllegalArgumentException(\"Unsupported class-loading strategy '\"\n                    + classLoadingStrategy + \"'. Supported values are: \" + STRATEGY_PARENT_FIRST\n                    + \", \" + STRATEGY_PLUGIN + \" and \" + STRATEGY_SELF_FIRST);\n        }\n        log.debug(\"Populating class realm {}\", realm.getId());\n        for (Artifact artifact : artifacts) {\n            String id = artifact.getGroupId() + \":\" + artifact.getArtifactId();\n            if (providedArtifacts.contains(id)) {\n                log.debug(\"  Excluded {}\", id);\n            } else {\n                File file = artifact.getFile();\n                log.debug(\"  Included {} located at {}\", id, file);\n                realm.addURL(file.toURI().toURL());\n            }\n        }\n        return CoreExtensionEntry.discoverFrom(\n                realm,\n                Collections.singleton(artifacts.get(0).getFile()),\n                extension.getGroupId() + \":\" + extension.getArtifactId(),","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/apache/maven/blob/e4093d4e120eac99d6bdce5ba67cace2f3085c97/compat/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java#L167-L203","documentation":"When loading a core extension from .mvn/extensions.xml, BootstrapCoreExtensionManager builds a class realm according to the extension's <classLoadingStrategy> element. Only 'parent-first', 'plugin', and 'self-first' are recognized; anything else throws IllegalArgumentException while bootstrapping the extension, before the build starts. The element is optional — the model defaults to 'self-first' (CoreExtension.java), so this error always means an explicitly written, invalid value.","triggerScenarios":"Editing .mvn/extensions.xml and typing <classLoadingStrategy>parent_first</classLoadingStrategy> (underscore instead of dash), 'parentFirst' (camelCase), ' plugin' (leading/trailing whitespace is trimmed by the reader, but inner spaces remain invalid), or a value copied from unrelated classloader documentation. The check happens during core-extension bootstrap for every build in that project.","commonSituations":"Hand-editing .mvn/extensions.xml based on memory or blog posts that use different spellings. Configuration management templating that mangles dashes. Copying from another build tool's realm-strategy vocabulary.","solutions":["Set <classLoadingStrategy> to exactly one of: parent-first, plugin, self-first (lowercase, hyphenated).","If unsure which strategy you need, remove the element entirely — the default self-first applies and the error disappears.","Use 'plugin' only when you intend to reuse the Maven core exported artifacts/packages; otherwise prefer the default.","Re-run with mvn -X to confirm the extension realm builds and the strategy is accepted."],"exampleFix":"<!-- before (.mvn/extensions.xml) -->\n<extension>\n  <groupId>org.example</groupId><artifactId>ext</artifactId><version>1.0</version>\n  <classLoadingStrategy>parentFirst</classLoadingStrategy>\n</extension>\n\n<!-- after -->\n<extension>\n  <groupId>org.example</groupId><artifactId>ext</artifactId><version>1.0</version>\n  <classLoadingStrategy>parent-first</classLoadingStrategy>\n</extension>","handlingStrategy":"validation","validationCode":"// Validate .mvn/extensions.xml before running mvn\nprivate static final Set<String> STRATEGIES = Set.of(\"parent-first\", \"plugin\", \"self-first\");\nvar doc = javax.xml.parsers.DocumentBuilderFactory.newInstance()\n        .newDocumentBuilder().parse(Path.of(\".mvn/extensions.xml\").toFile());\nvar nodes = doc.getElementsByTagName(\"classLoadingStrategy\");\nfor (int i = 0; i < nodes.getLength(); i++) {\n    String v = nodes.item(i).getTextContent().trim();\n    if (!STRATEGIES.contains(v)) {\n        throw new IllegalArgumentException(\"Bad classLoadingStrategy '\" + v + \"' in extensions.xml\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    cli.doMain(args, workingDir, ...);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Unsupported class-loading strategy\")) {\n        // fix or strip the <classLoadingStrategy> element (default self-first) and retry\n    }\n    throw e;\n}","preventionTips":["Validate .mvn/extensions.xml in a pre-commit hook or CI lint step (exact strategy spellings: parent-first, plugin, self-first).","Omit <classLoadingStrategy> unless you specifically understand realm semantics — the default is self-first.","Treat any edit to extensions.xml as a reviewed config change; run mvn -X once afterwards to confirm the realm builds."],"tags":["maven","core-extensions","classloading","extensions-xml","invalid-value"],"backgroundTag":"invalid-enum-config-value","analyzedSha":"e4093d4e120eac99d6bdce5ba67cace2f3085c97","analyzedAt":"2026-08-21T22:58:24.034Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}