{"record":{"id":"5dc8f8618c67fb62","repo":"quarkusio/quarkus","slug":"failed-to-instantiate-declared-threadcontextprovid","errorCode":null,"errorMessage":"Failed to instantiate declared ThreadContextProvider class: ","messagePattern":"Failed to instantiate declared ThreadContextProvider class: ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/smallrye-context-propagation/deployment/src/main/java/io/quarkus/smallrye/context/deployment/SmallRyeContextPropagationProcessor.java","lineNumber":76,"sourceCode":"        additionalBeans\n                .produce(AdditionalBeanBuildItem.unremovableOf(SmallRyeContextPropagationProvider.class));\n    }\n\n    @BuildStep\n    @Record(ExecutionTime.STATIC_INIT)\n    void buildStatic(SmallRyeContextPropagationRecorder recorder, List<ThreadContextProviderBuildItem> threadContextProviders)\n            throws ClassNotFoundException, IOException {\n        List<ThreadContextProvider> discoveredProviders = new ArrayList<>();\n        List<ContextManagerExtension> discoveredExtensions = new ArrayList<>();\n        List<Class<?>> providers = threadContextProviders.stream().map(ThreadContextProviderBuildItem::getProvider)\n                .collect(Collectors.toCollection(ArrayList::new));\n        ServiceUtil.classesNamedIn(Thread.currentThread().getContextClassLoader(),\n                \"META-INF/services/\" + ThreadContextProvider.class.getName()).forEach(providers::add);\n        for (Class<?> provider : providers) {\n            try {\n                discoveredProviders.add((ThreadContextProvider) provider.getDeclaredConstructor().newInstance());\n            } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {\n                throw new RuntimeException(\"Failed to instantiate declared ThreadContextProvider class: \" + provider.getName(),\n                        e);\n            }\n        }\n        for (Class<?> extension : ServiceUtil.classesNamedIn(Thread.currentThread().getContextClassLoader(),\n                \"META-INF/services/\" + ContextManagerExtension.class.getName())) {\n            try {\n                discoveredExtensions.add((ContextManagerExtension) extension.getDeclaredConstructor().newInstance());\n            } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {\n                throw new RuntimeException(\"Failed to instantiate declared ThreadContextProvider class: \" + extension.getName(),\n                        e);\n            }\n        }\n\n        recorder.configureStaticInit(discoveredProviders, discoveredExtensions);\n    }\n\n    @BuildStep\n    @Record(ExecutionTime.RUNTIME_INIT)","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/smallrye-context-propagation/deployment/src/main/java/io/quarkus/smallrye/context/deployment/SmallRyeContextPropagationProcessor.java#L58-L94","documentation":"During static-init build of the context propagation extension, SmallRyeContextPropagationProcessor discovers all ThreadContextProvider implementations declared in META-INF/services and instantiates each via a no-arg constructor. If instantiation fails, the build step aborts with a RuntimeException naming the provider class, because a broken context provider would silently break context propagation.","triggerScenarios":"A ThreadContextProvider service-declared class has no public no-arg constructor, is abstract, is not actually a ThreadContextProvider, or throws in its constructor when loaded at static init (e.g. it depends on runtime-only CDI beans or config).","commonSituations":"Adding a custom ThreadContextProvider that injects CDI beans or reads runtime config in its constructor; provider class from a dependency incompatible at build time; missing default constructor after refactor.","solutions":["Give the provider a public no-arg constructor with no runtime dependencies in its body","Move CDI/config lookups out of the constructor into threadContext()","Verify the class implements org.eclipse.microprofile.context.ThreadContextProvider","Check the service file entry names the correct fully-qualified class"],"exampleFix":"// before\nclass MyProvider implements ThreadContextProvider {\n    MyProvider() { ConfigProvider.getConfig(); ... }\n}\n// after\nclass MyProvider implements ThreadContextProvider {\n    public MyProvider() {}\n    public ThreadContextSnapshot currentContext(Map<String, String> p) { ... }\n}","handlingStrategy":"try-catch","validationCode":"try {\n    var ctor = providerClass.getDeclaredConstructor();\n    ctor.setAccessible(true);\n    ctor.newInstance();\n} catch (ReflectiveOperationException e) {\n    throw new IllegalStateException(\"Bad ThreadContextProvider: \" + providerClass.getName(), e);\n}","typeGuard":"boolean validProvider(Class<?> c) {\n    return ThreadContextProvider.class.isAssignableFrom(c)\n        && !c.isInterface() && !Modifier.isAbstract(c.getModifiers())\n        && Arrays.stream(c.getConstructors()).anyMatch(k -> k.getParameterCount() == 0);\n}","tryCatchPattern":"try { runBuild(); }\ncatch (RuntimeException e) {\n    if (e.getMessage().startsWith(\"Failed to instantiate declared ThreadContextProvider\")) {\n        log.error(\"Check constructor of provider: \" + extractName(e.getMessage()));\n    }\n}","preventionTips":["Keep ThreadContextProvider constructors empty and side-effect free","Never inject CDI beans or runtime config in the provider constructor","Keep META-INF/services entries in sync with actual classes","Test provider loading in a plain JVM before adding to the app"],"tags":["build-time","classpath","service-loader","context-propagation"],"backgroundTag":"service-provider-instantiation-failed","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}