quarkusio/quarkus · error · IllegalArgumentException
service interface name cannot be null or blank
Error message
service interface name cannot be null or blank
What it means
ServiceProviderBuildItem.allProviders() registers all providers from a service descriptor file for native image inclusion. It validates the service interface class name is non-null and non-blank before reading the descriptor, throwing IllegalArgumentException otherwise.
Source
Thrown at core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/ServiceProviderBuildItem.java:46
private static final PathFilter SPI_FILTER = PathFilter.forIncludes(List.of(SPI_ROOT + "*"));
private final String serviceInterface;
private final List<String> providers;
/**
* Creates and returns a {@link ServiceProviderBuildItem} for the {@code serviceInterfaceClassName} by including
* all the providers that are listed in the service interface descriptor file.
*
* @param serviceInterfaceClassName the interface whose service interface descriptor file we want to embed
* @param serviceInterfaceDescriptorFile the path to the service interface descriptor file
* @return
* @throws IOException
*/
public static ServiceProviderBuildItem allProviders(final String serviceInterfaceClassName,
final Path serviceInterfaceDescriptorFile)
throws IOException {
if (serviceInterfaceClassName == null || serviceInterfaceClassName.trim().isEmpty()) {
throw new IllegalArgumentException("service interface name cannot be null or blank");
}
if (serviceInterfaceDescriptorFile == null) {
throw new IllegalArgumentException("service interface descriptor file path cannot be null");
}
final Set<String> classNames = new LinkedHashSet<>();
final List<String> lines = Files.readAllLines(serviceInterfaceDescriptorFile, StandardCharsets.UTF_8);
// parse each line and add each listed provider
for (String line : lines) {
final int commentIndex = line.indexOf('#');
if (commentIndex >= 0) {
// strip off anything after the # (including the #)
line = line.substring(0, commentIndex);
}
line = line.trim();
if (!line.isEmpty()) {
classNames.add(line);
}
}View on GitHub (pinned to e1c734241f)
Solutions
- Pass the fully-qualified service interface name (e.g. "com.example.MySpi")
- Verify the constant/variable supplying the name is populated before calling
- Add a null/blank check with a clear failure at the call site
Example fix
// before
ServiceProviderBuildItem.allProviders(spiName, descriptorPath);
// after
Objects.requireNonNull(spiName, "spiName required");
if (spiName.isBlank()) throw new IllegalStateException("spi not configured");
ServiceProviderBuildItem.allProviders(spiName, descriptorPath); Defensive patterns
Strategy: validation
Validate before calling
if (serviceInterfaceClassName == null || serviceInterfaceClassName.trim().isEmpty()) throw new IllegalStateException("SPI interface name required"); Type guard
boolean isValidClassName(String s) { return s != null && !s.trim().isEmpty(); } Try / catch
try { item = ServiceProviderBuildItem.allProviders(name, path); } catch (IllegalArgumentException e) { log.error("Invalid SPI name", e); throw e; } Prevention
- Always pass hardcoded or verified fully-qualified interface names
- Validate computed names before calling factory methods
- Keep SPI names in constants rather than dynamic strings
When it happens
Trigger: Calling ServiceProviderBuildItem.allProviders(null, path) or allProviders(" ", path) from a build step.
Common situations: Dynamically computed service interface name resolves to null (missing class metadata) or an empty string after trimming; misconfigured build-step parameters.
Related errors
- The serviceDescriptorFile interface cannot be blank
- The provider class name cannot be null or blank
- service interface descriptor file path cannot be null
- Could not read class path resources having path '${resourceP
- Extra steps left over
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/4a3a28fd31c75558.
Report an issue: GitHub.