{"record":{"id":"32c794f2108becda","repo":"junit-team/junit5","slug":"third-party-testengine-s-is-forbidden-to-use-th","errorCode":null,"errorMessage":"Third-party TestEngine '%s' is forbidden to use the reserved '%s' TestEngine ID.","messagePattern":"Third-party TestEngine '(.+?)' is forbidden to use the reserved '(.+?)' TestEngine ID\\.","errorType":"exception","errorClass":"JUnitException","httpStatus":null,"severity":"error","filePath":"junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java","lineNumber":82,"sourceCode":"\t}\n\n\tprivate static @Nullable String wellKnownClassNameForEngineId(TestEngine testEngine) {\n\t\tString engineId = Preconditions.notBlank(testEngine.getId(),\n\t\t\t() -> \"ID for TestEngine [%s] must not be null or blank\".formatted(testEngine.getClass().getName()));\n\t\treturn switch (engineId) {\n\t\t\tcase \"junit-jupiter\" -> \"org.junit.jupiter.engine.JupiterTestEngine\";\n\t\t\tcase \"junit-vintage\" -> \"org.junit.vintage.engine.VintageTestEngine\";\n\t\t\tcase \"junit-platform-suite\" -> \"org.junit.platform.suite.engine.SuiteTestEngine\";\n\t\t\tdefault -> null;\n\t\t};\n\t}\n\n\tprivate static void validateWellKnownClassName(TestEngine testEngine, String expectedClassName) {\n\t\tString actualClassName = testEngine.getClass().getName();\n\t\tif (actualClassName.equals(expectedClassName)) {\n\t\t\treturn;\n\t\t}\n\t\tthrow new JUnitException(\n\t\t\t\"Third-party TestEngine '%s' is forbidden to use the reserved '%s' TestEngine ID.\".formatted(\n\t\t\t\tactualClassName, testEngine.getId()));\n\t}\n\n}\n","sourceCodeStart":64,"sourceCodeEnd":88,"githubUrl":"https://github.com/junit-team/junit5/blob/f070c699a08b5d8393df9afd147af5c5e90bb21b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java#L64-L88","documentation":"EngineIdValidator.validateWellKnownClassName throws if a TestEngine uses a reserved well-known id (junit-jupiter, junit-vintage, junit-platform-suite) but its implementing class is not the expected built-in class. This blocks third-party engines from impersonating the official engines via id squatting.","triggerScenarios":"A TestEngine returns 'junit-jupiter', 'junit-vintage', or 'junit-platform-suite' from getId() but its class name is not org.junit.jupiter.engine.JupiterTestEngine / org.junit.vintage.engine.VintageTestEngine / org.junit.platform.suite.engine.SuiteTestEngine respectively.","commonSituations":"A custom/forked engine deliberately reusing an official id; a test fixture/fake engine stub that hardcodes 'junit-jupiter' as its id; a renamed/shaded copy of an official engine whose class name no longer matches the expected one; mocking frameworks that create TestEngine proxies with a fixed id.","solutions":["Give the custom engine a unique, non-reserved id (avoid the 'junit-' prefix and the well-known ids).","If you actually need the official engine, depend on the real artifact instead of a fork/stub.","For test doubles, use an id like 'test-fake-engine' rather than a reserved id."],"exampleFix":"// before\npublic class MyEngine implements TestEngine {\n    public String getId() { return \"junit-jupiter\"; } // reserved -> throws\n}\n// after\npublic class MyEngine implements TestEngine {\n    public String getId() { return \"my-custom-engine\"; }\n}","handlingStrategy":"validation","validationCode":"// Reject reserved ids for custom engines at authoring time\nprivate static final Set<String> RESERVED = Set.of(\"junit-jupiter\",\"junit-vintage\",\"junit-platform-suite\");\nString id = myEngine.getId();\nif (RESERVED.contains(id) && !wellKnownClassNameFor(id).equals(myEngine.getClass().getName()))\n    throw new IllegalArgumentException(\"reserved engine id: \" + id);","typeGuard":"static boolean isReservedId(String id) {\n    return Set.of(\"junit-jupiter\",\"junit-vintage\",\"junit-platform-suite\").contains(id);\n}","tryCatchPattern":"try {\n    LauncherFactory.create();\n} catch (JUnitException e) {\n    if (e.getMessage().contains(\"forbidden to use the reserved\")) {\n        // rename the custom engine id and recreate\n    }\n}","preventionTips":["Custom engines must not use the 'junit-' prefix or the well-known ids.","Use a distinctive id for forks/stubs (e.g. 'mycompany-test-engine').","For test doubles, avoid impersonating official engines."],"tags":["engine-id","reserved","third-party","validation"],"backgroundTag":null,"analyzedSha":"f070c699a08b5d8393df9afd147af5c5e90bb21b","analyzedAt":"2026-08-11T20:31:00.530Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}