{"record":{"id":"d7ec9c849e817f65","repo":"apache/pulsar","slug":"user-class-must-be-concrete","errorCode":null,"errorMessage":"User class must be concrete","messagePattern":"User class must be concrete","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"pulsar-common/src/main/java/org/apache/pulsar/common/util/Reflections.java","lineNumber":90,"sourceCode":"            throw new RuntimeException(\"User class must be in class path\", cnfe);\n        }\n        if (!xface.isAssignableFrom(theCls)) {\n            throw new RuntimeException(userClassName + \" does not implement \" + xface.getName());\n        }\n        @SuppressWarnings(\"unchecked\") // safe: theCls is verified to be assignable to xface\n        Class<T> tCls = (Class<T>) theCls.asSubclass(xface);\n        T result;\n        try {\n            @SuppressWarnings(\"unchecked\") // safe: constructor cache is keyed by theCls which extends T\n            Constructor<T> meth = (Constructor<T>) constructorCache.get(theCls);\n            if (null == meth) {\n                meth = tCls.getDeclaredConstructor();\n                meth.setAccessible(true);\n                constructorCache.put(theCls, meth);\n            }\n            result = meth.newInstance();\n        } catch (InstantiationException ie) {\n            throw new RuntimeException(\"User class must be concrete\", ie);\n        } catch (NoSuchMethodException e) {\n            throw new RuntimeException(\"User class must have a no-arg constructor\", e);\n        } catch (IllegalAccessException e) {\n            throw new RuntimeException(\"User class must have a public constructor\", e);\n        } catch (InvocationTargetException e) {\n            throw new RuntimeException(\"User class constructor throws exception\", e);\n        }\n        return result;\n\n    }\n\n    /**\n     * Create an instance of <code>userClassName</code> using provided <code>classLoader</code>.\n     *\n     * @param userClassName user class name\n     * @param classLoader class loader to load the class.\n     * @return the instance\n     */","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-common/src/main/java/org/apache/pulsar/common/util/Reflections.java#L72-L108","documentation":"createInstance instantiates the class reflectively via a no-arg constructor. InstantiationException is thrown by newInstance() when the class is abstract or an interface, so it is wrapped in this RuntimeException. It means the configured user class cannot be instantiated because it is not concrete.","triggerScenarios":"Configuring an abstract class or interface name as the user class, so Constructor.newInstance() raises InstantiationException.","commonSituations":"Pointing config at a base/abstract adapter class instead of a concrete subclass; refactoring left only abstract implementations in a plugin jar.","solutions":["Configure the fully qualified name of a concrete (non-abstract) class","Make the class concrete by implementing all abstract methods, or add a concrete subclass and use that","Check the plugin jar actually contains the concrete implementation, not only the abstract base"],"exampleFix":"// before\npublic abstract class MyFilter implements Filter { }\n// after\npublic class MyConcreteFilter extends MyFilter { } // use MyConcreteFilter in config","handlingStrategy":"validation","validationCode":"// reject abstract classes/interfaces before instantiation\nClass<?> cls = Class.forName(className, true, classLoader);\nif (Modifier.isAbstract(cls.getModifiers()) || cls.isInterface()) {\n    throw new IllegalArgumentException(\"Configured class must be concrete: \" + className);\n}","typeGuard":"boolean isConcrete(Class<?> cls) { return !cls.isInterface() && !Modifier.isAbstract(cls.getModifiers()); }","tryCatchPattern":"try {\n    T obj = Reflections.createInstance(className, XFace.class, classLoader);\n} catch (RuntimeException e) {\n    if (e.getMessage().equals(\"User class must be concrete\")) {\n        throw new IllegalArgumentException(\"Configure a concrete subclass of \" + className, e);\n    }\n    throw e;\n}","preventionTips":["Reference concrete implementation classes in config, never base/adapter classes","Check for the implicit-default-constructor trap when adding parameterized constructors","Ship at least one concrete class in every plugin jar and document its FQN"],"tags":["reflection","instantiation","configuration"],"backgroundTag":"class-not-instantiable","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}