quarkusio/quarkus · error · IllegalStateException
Classloader is not resettable
Error message
Classloader is not resettable
What it means
QuarkusClassLoader.reset() can only be called on a classloader that was created with a resettable element (a memory class-path element that supports regeneration). If the loader has no resettableElement, reset() throws IllegalStateException("Classloader is not resettable").
Source
Thrown at independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java:233
if (name.startsWith("/")) {
name = name.substring(1);
}
if (name.endsWith("/")) {
name = name.substring(0, name.length() - 1);
}
return name;
}
private boolean parentFirst(String name, ClassPathResourceIndex classPathResourceIndex) {
return parentFirst || name.startsWith("io/quarkus/devservices/crossclassloader")
|| classPathResourceIndex.isParentFirst(name);
}
public void reset(Map<String, byte[]> generatedResources, Map<String, byte[]> transformedClasses) {
ensureOpen();
if (resettableElement == null) {
throw new IllegalStateException("Classloader is not resettable");
}
synchronized (this) {
// we don't want the previous MemoryClassPathElement to leak as a key of protectionDomains
protectionDomains.remove(this.transformedClasses);
this.transformedClasses = new MemoryClassPathElement(transformedClasses, true);
resettableElement.reset(generatedResources);
classPathResourceIndex = null;
}
}
/**
* Returns all in-memory generated and transformed class bytes, keyed by
* resource path (e.g. {@code io/quarkus/runner/Foo.class}).
* <p>
* Classes are collected in classloader priority order: transformed classes
* first, then resettable element, then normal priority elements, then
* lesser priority elements. Only {@link MemoryClassPathElement} instances
* are included. Uses {@code putIfAbsent} so higher-priority entries win.View on GitHub (pinned to e1c734241f)
Solutions
- Only call reset() on the QuarkusClassLoader instance created for dev mode / the StartupAction, not the base loader
- Check how the classloader was constructed and enable the resettable memory element if you control creation
- Replace the classloader (restart the StartupAction) instead of resetting when the loader is not resettable
Example fix
// before baseQuarkusClassLoader.reset(newResources, transformed); // IllegalStateException // after QuarkusClassLoader appLoader = (QuarkusClassLoader) startupAction.getClassLoader(); appLoader.reset(newResources, transformed);
Defensive patterns
Strategy: type-guard
Validate before calling
public static void resetIfResettable(QuarkusClassLoader cl, Map<String, byte[]> gen, Map<String, byte[]> transformed) {
if (cl == null) throw new IllegalStateException("No application classloader");
cl.reset(gen, transformed);
} Type guard
boolean isResettable(QuarkusClassLoader cl) {
// only dev-mode / startup-action loaders are resettable
return cl != null && cl.getParent() != null
&& "io.quarkus.dev.runtime.QuarkusClassLoader".equals(cl.getClass().getName()) == false
? cl.getClass().getName().contains("QuarkusClassLoader") : cl != null;
}
// safer: track the loader you got from the StartupAction and only reset that instance Try / catch
try {
loader.reset(generated, transformed);
} catch (IllegalStateException e) {
// loader not resettable -> restart the StartupAction instead of resetting
} Prevention
- Only reset the classloader obtained from the current StartupAction / dev-mode context
- Never call reset() on the base (root) QuarkusClassLoader
- If unsure, create a new StartupAction rather than resetting
When it happens
Trigger: Calling QuarkusClassLoader.reset(generatedResources, transformedClasses) on a loader built without the resettable flag — e.g. a base/production QuarkusClassLoader rather than the dev-mode or test resettable loader.
Common situations: Invoking reset() from custom tooling on a non-resettable classloader; live-reload code paths executed against a loader created without reset support; mixing up the base loader with the application loader in tests.
Related errors
- Unable to read
- Failed to load steps from %s
- The class (${name}) cannot be created during deployment.
- Hot deployment of the application is not supported when upda
- Cannot find ClassLoadingRecorder.class on classpath
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/913e3a907f279fc9.
Report an issue: GitHub.