{"record":{"id":"4b513deb6e96c8c0","repo":"quarkusio/quarkus","slug":"cannot-write-service-provider-file-resourcename","errorCode":null,"errorMessage":"Cannot write service provider file '${resourceName}': this GeneratedClassGizmo2Adaptor was created without a GeneratedServiceProviderBuildItem producer","messagePattern":"Cannot write service provider file '(.+?)': this GeneratedClassGizmo2Adaptor was created without a GeneratedServiceProviderBuildItem producer","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"core/deployment/src/main/java/io/quarkus/deployment/GeneratedClassGizmo2Adaptor.java","lineNumber":87,"sourceCode":"        };\n    }\n\n    @Deprecated\n    public GeneratedClassGizmo2Adaptor(BuildProducer<GeneratedClassBuildItem> generatedClasses,\n            final BuildProducer<GeneratedResourceBuildItem> generatedResources,\n            Function<String, String> generatedToBaseNameFunction) {\n        this(generatedClasses, generatedResources, null, generatedToBaseNameFunction);\n    }\n\n    @Override\n    public void write(String resourceName, byte[] bytes) {\n        if (resourceName.endsWith(\".class\")) {\n            String className = resourceName.substring(0, resourceName.length() - 6).replace('/', '.');\n            generatedClasses.produce(\n                    new GeneratedClassBuildItem(applicationClassPredicate.test(className), className, bytes));\n        } else if (resourceName.startsWith(\"META-INF/services/\")) {\n            if (generatedServiceProviders == null) {\n                throw new IllegalStateException(\n                        \"Cannot write service provider file '\" + resourceName\n                                + \"': this GeneratedClassGizmo2Adaptor was created without a GeneratedServiceProviderBuildItem producer\");\n            }\n            String serviceInterfaceName = resourceName.substring(\"META-INF/services/\".length());\n            for (String line : new String(bytes, StandardCharsets.UTF_8).split(\"\\\\r?\\\\n\")) {\n                line = line.trim();\n                if (!line.isEmpty() && !line.startsWith(\"#\")) {\n                    generatedServiceProviders.produce(new GeneratedServiceProviderBuildItem(serviceInterfaceName, line));\n                }\n            }\n        } else {\n            generatedResources.produce(\n                    new GeneratedResourceBuildItem(resourceName, bytes));\n        }\n    }\n\n    public static boolean isApplicationClass(String className) {\n        return QuarkusClassLoader.isApplicationClass(className);","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/deployment/src/main/java/io/quarkus/deployment/GeneratedClassGizmo2Adaptor.java#L69-L105","documentation":"GeneratedClassGizmo2Adaptor can emit GeneratedClassBuildItem for .class resources and GeneratedServiceProviderBuildItem for META-INF/services/ files, but the latter requires a producer build item supplied at construction. If the adaptor was created without one and bytecode attempts to write a service-provider file, writing is refused with IllegalStateException.","triggerScenarios":"Code generated via Gizmo2 calls write() with a resource named META-INF/services/<Interface> while the adaptor instance was constructed with generatedServiceProviders == null (no GeneratedServiceProviderBuildItem producer passed to the constructor).","commonSituations":"A build step generates classes plus service provider files but only injects GeneratedClassBuildItem (not the provider producer); copy-pasting adaptor construction between steps; adding SPI registration to existing generated-class code.","solutions":["Construct the adaptor passing a BuildProducer<GeneratedServiceProviderBuildItem> (inject it into the build step).","Register the service provider directly via a ServicesFileBuildItem or @BuildStep producing GeneratedServiceProviderBuildItem instead of writing through this adaptor.","Remove the META-INF/services write from generated code and register the implementation with Quarkus' own service-registration build items."],"exampleFix":"// before\nvar adaptor = new GeneratedClassGizmo2Adaptor(generatedClasses, predicate, null);\n// after\nvar adaptor = new GeneratedClassGizmo2Adaptor(generatedClasses, predicate, generatedServiceProviders);\n// where generatedServiceProviders is an injected BuildProducer<GeneratedServiceProviderBuildItem>","handlingStrategy":"validation","validationCode":"Objects.requireNonNull(generatedServiceProviders,\n    \"GeneratedClassGizmo2Adaptor needs a GeneratedServiceProviderBuildItem producer to write META-INF/services files\");","typeGuard":"static boolean canWriteServiceProviders(GeneratedClassGizmo2Adaptor a) {\n    return a != null && a.hasServiceProviderProducer();\n}","tryCatchPattern":"try {\n    adaptor.write(resourceName, bytes);\n} catch (IllegalStateException e) {\n    if (e.getMessage().startsWith(\"Cannot write service provider file\")) {\n        // register via GeneratedServiceProviderBuildItem instead\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always inject and pass BuildProducer<GeneratedServiceProviderBuildItem> when generating SPI files.","Prefer Quarkus' service-registration build items over writing META-INF/services directly.","Check the adaptor constructor contract before reuse in new build steps."],"tags":["quarkus","build-step","gizmo","service-provider"],"backgroundTag":"missing-build-item-producer","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"}