quarkusio/quarkus · error · IllegalStateException
Cannot write service provider file '${resourceName}': this G
Error message
Cannot write service provider file '${resourceName}': this GeneratedClassGizmo2Adaptor was created without a GeneratedServiceProviderBuildItem producer What it means
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.
Source
Thrown at core/deployment/src/main/java/io/quarkus/deployment/GeneratedClassGizmo2Adaptor.java:87
};
}
@Deprecated
public GeneratedClassGizmo2Adaptor(BuildProducer<GeneratedClassBuildItem> generatedClasses,
final BuildProducer<GeneratedResourceBuildItem> generatedResources,
Function<String, String> generatedToBaseNameFunction) {
this(generatedClasses, generatedResources, null, generatedToBaseNameFunction);
}
@Override
public void write(String resourceName, byte[] bytes) {
if (resourceName.endsWith(".class")) {
String className = resourceName.substring(0, resourceName.length() - 6).replace('/', '.');
generatedClasses.produce(
new GeneratedClassBuildItem(applicationClassPredicate.test(className), className, bytes));
} else if (resourceName.startsWith("META-INF/services/")) {
if (generatedServiceProviders == null) {
throw new IllegalStateException(
"Cannot write service provider file '" + resourceName
+ "': this GeneratedClassGizmo2Adaptor was created without a GeneratedServiceProviderBuildItem producer");
}
String serviceInterfaceName = resourceName.substring("META-INF/services/".length());
for (String line : new String(bytes, StandardCharsets.UTF_8).split("\\r?\\n")) {
line = line.trim();
if (!line.isEmpty() && !line.startsWith("#")) {
generatedServiceProviders.produce(new GeneratedServiceProviderBuildItem(serviceInterfaceName, line));
}
}
} else {
generatedResources.produce(
new GeneratedResourceBuildItem(resourceName, bytes));
}
}
public static boolean isApplicationClass(String className) {
return QuarkusClassLoader.isApplicationClass(className);View on GitHub (pinned to e1c734241f)
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.
Example fix
// before var adaptor = new GeneratedClassGizmo2Adaptor(generatedClasses, predicate, null); // after var adaptor = new GeneratedClassGizmo2Adaptor(generatedClasses, predicate, generatedServiceProviders); // where generatedServiceProviders is an injected BuildProducer<GeneratedServiceProviderBuildItem>
Defensive patterns
Strategy: validation
Validate before calling
Objects.requireNonNull(generatedServiceProviders,
"GeneratedClassGizmo2Adaptor needs a GeneratedServiceProviderBuildItem producer to write META-INF/services files"); Type guard
static boolean canWriteServiceProviders(GeneratedClassGizmo2Adaptor a) {
return a != null && a.hasServiceProviderProducer();
} Try / catch
try {
adaptor.write(resourceName, bytes);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Cannot write service provider file")) {
// register via GeneratedServiceProviderBuildItem instead
} else {
throw e;
}
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- %s is marked @Record but does not inject an @Recorder object
- One of either visitorFunction or inputTransformer must be se
- Unsupported object of type ${object.getClass()}. Supported t
- Failed to locate resources.txt in the project's resources
- Failed to copy " + p + " to " + output
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/4b513deb6e96c8c0.
Report an issue: GitHub.