{"record":{"id":"7d4f145eb46de77b","repo":"jenkinsci/jenkins","slug":"expected-1-instance-of-type-getname-but-got","errorCode":null,"errorMessage":"Expected 1 instance of ${type.getName()} but got ${all.size()}","messagePattern":"Expected 1 instance of (.+?) but got (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/hudson/ExtensionList.java","lineNumber":458,"sourceCode":"\n    /**\n     * Convenience method allowing lookup of the only instance of a given type.\n     * Equivalent to {@code ExtensionList.lookup(Class).get(Class)} if there is one instance,\n     * and throws an {@code IllegalStateException} otherwise.\n     *\n     * @param type The type to look up.\n     * @return the singleton instance of the given type in its list.\n     * @throws IllegalStateException if there are no instances, or more than one\n     *\n     * @since 2.87\n     */\n    public static @NonNull <U> U lookupSingleton(Class<U> type) {\n        ExtensionList<U> all = lookup(type);\n        if (Main.isUnitTest && all.isEmpty()) {\n            throw new IllegalStateException(\"Found no instances of \" + type.getName() +\n                \" registered (possible annotation processor issue); try using `mvn clean test -Dtest=…` rather than an IDE test runner\");\n        } else if (all.size() != 1) {\n            throw new IllegalStateException(\"Expected 1 instance of \" + type.getName() + \" but got \" + all.size());\n        }\n        return all.getFirst();\n    }\n\n    /**\n     * Convenience method allowing lookup of the instance of a given type with the highest ordinal.\n     * Equivalent to {@code ExtensionList.lookup(type).get(0)} if there is at least one instance,\n     * and throws an {@link IllegalStateException} otherwise if no instance could be found.\n     *\n     * @param type The type to look up.\n     * @return the singleton instance of the given type in its list.\n     * @throws IllegalStateException if there are no instances\n     *\n     * @since 2.435\n     */\n    public static @NonNull <U> U lookupFirst(Class<U> type) {\n        var all = lookup(type);\n        if (!all.isEmpty()) {","sourceCodeStart":440,"sourceCodeEnd":476,"githubUrl":"https://github.com/jenkinsci/jenkins/blob/2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc/core/src/main/java/hudson/ExtensionList.java#L440-L476","documentation":"Thrown by ExtensionList.lookupSingleton when more than one instance of the requested type is registered. lookupSingleton demands exactly one; in unit-test mode an empty list gives a different message, but any count other than 1 (including 0 in non-test mode) hits this branch. This guards callers that cannot disambiguate duplicates.","triggerScenarios":"Two @Extension classes (or two registrations) of the same type are both loaded; a test registers a mock plus the real one; a plugin and core both register the same extension point; duplicate registrations from a fat jar.","commonSituations":"Plugin provides an extension point already provided by core or another installed plugin; test harness adds a duplicate; split-package issue loading the same class twice.","solutions":["Find and remove the duplicate @Extension registration (check the message's count and inspect manage/extensions).","If duplicates are legitimate, use lookupFirst instead to pick the highest-ordinal instance.","Adjust @Extension ordinal to make one registration win and the other effectively shadowed (still counted, so prefer removal).","In tests, ensure only one instance is registered; reset the ExtensionList between tests."],"exampleFix":"// before\nvar s = ExtensionList.lookupSingleton(MyService.class); // 2 registered\n// after\nvar s = ExtensionList.lookupFirst(MyService.class); // accepts duplicates, picks top","handlingStrategy":"validation","validationCode":"ExtensionList<MyService> all = ExtensionList.lookup(MyService.class);\nif (all.size() != 1) {\n    // duplicates or none — decide policy before calling lookupSingleton\n}","typeGuard":"static boolean isSingletonRegistered(Class<?> type) {\n    return ExtensionList.lookup(type).size() == 1;\n}","tryCatchPattern":"try {\n    var s = ExtensionList.lookupSingleton(MyService.class);\n} catch (IllegalStateException e) {\n    // 'Expected 1 instance ... but got N' — use lookupFirst or remove the duplicate\n    var s = ExtensionList.lookupFirst(MyService.class);\n}","preventionTips":["Avoid registering the same extension point from two plugins.","In tests, reset the ExtensionList or use a single registration.","Audit manage/extensions after plugin installs to catch duplicates early."],"tags":["extension-list","singleton","duplicate-registration"],"backgroundTag":null,"analyzedSha":"2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc","analyzedAt":"2026-08-14T07:07:15.274Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}