quarkusio/quarkus · error · IllegalArgumentException
%s is not a valid resource name as it doesn't end with .clas
Error message
%s is not a valid resource name as it doesn't end with .class
What it means
ClassLoaderHelper.fromResourceNameToClassName() converts a class-file resource name (e.g. 'com/acme/Foo.class') into a class name ('com.acme.Foo') and refuses any resource that doesn't end with the '.class' suffix, throwing IllegalArgumentException. This guards against silently producing garbage class names from non-class resources.
Source
Thrown at independent-projects/bootstrap/classloader-commons/src/main/java/io/quarkus/commons/classloading/ClassLoaderHelper.java:36
*
* @param className
* @return the name of the respective resource
*/
public static String fromClassNameToResourceName(final String className) {
//Important: avoid indy!
return className.replace('.', '/').concat(CLASS_SUFFIX);
}
/**
* Helper method to convert a resource name into the corresponding class name:
* replace all "/" with "." and remove the ".class" postfix.
*
* @param resourceName
* @return the name of the respective class
*/
public static String fromResourceNameToClassName(final String resourceName) {
if (!resourceName.endsWith(CLASS_SUFFIX)) {
throw new IllegalArgumentException(
String.format("%s is not a valid resource name as it doesn't end with .class", resourceName));
}
return resourceName.substring(0, resourceName.length() - CLASS_SUFFIX.length()).replace('/', '.');
}
public static boolean isInJdkPackage(String name) {
return name.startsWith(JAVA) || name.startsWith(JDK_INTERNAL) || name.startsWith(SUN_MISC);
}
/**
* Returns {@code true} if the resource name represents a regular class file,
* excluding {@code module-info.class} and {@code package-info.class}.
*
* @param resourceName the JAR entry path, e.g. {@code com/example/Foo.class}
*/
public static boolean isClassEntry(String resourceName) {
return resourceName.endsWith(CLASS_SUFFIX)View on GitHub (pinned to e1c734241f)
Solutions
- Filter resource names with name.endsWith(".class") before calling the method
- Strip query/trailing characters (like '/' or '!/...') from resource URLs so the name really ends in '.class'
- If the resource is not a class, do not convert it — handle it in a separate code path
Example fix
// before
String cn = ClassLoaderHelper.fromResourceNameToClassName("META-INF/beans.xml");
// after
if (resource.endsWith(".class")) {
String cn = ClassLoaderHelper.fromResourceNameToClassName(resource);
} Defensive patterns
Strategy: validation
Validate before calling
String toClassName(String resource) {
if (!resource.endsWith(".class")) {
return null; // not a class resource; skip
}
return ClassLoaderHelper.fromResourceNameToClassName(resource);
} Type guard
boolean isClassResource(String name) {
return name != null && name.endsWith(".class") && !name.endsWith(".class/");
} Try / catch
try {
return ClassLoaderHelper.fromResourceNameToClassName(resourceName);
} catch (IllegalArgumentException e) {
if (e.getMessage().endsWith("doesn't end with .class")) {
log.debugf("Skipping non-class resource: %s", resourceName);
return null;
}
throw e;
} Prevention
- Filter scanner/index results with endsWith(".class") before conversion
- Clean resource URLs of suffixes like '!/...' or trailing '/' before passing them in
- Keep non-class resources on a separate processing path
When it happens
Trigger: Calling ClassLoaderHelper.fromResourceNameToClassName() with paths like 'com/acme/Foo', 'META-INF/beans.xml', 'com/acme/Foo.class/', or any resource not ending exactly in '.class'.
Common situations: Scanning classloader resources and passing every entry to the converter without filtering by suffix; index entries for nested class sources or generated resources mixed in with class files; off-by-one slicing that dropped '.class' before the call.
Related errors
- Extra steps left over
- Unknown start character for json value: %s
- Failed to load steps from %s
- name cannot be null
- The class (${name}) cannot be created during deployment.
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/1606acc4b9d913fd.
Report an issue: GitHub.