oracle/graal · error · LoadingConstraintViolationException
New loading constraint violates an older one!
Error message
New loading constraint violates an older one!
What it means
While merging/registering loading constraints, LoadingConstraintsShared.checkConstraint detects that an existing constraint for a type symbol is already bound to a loaded class (c1.klass) and the new constraint names a different loaded class. Because both classes exist and differ, the new constraint contradicts the recorded one and LoadingConstraintViolationException is thrown.
Source
Thrown at espresso-shared/src/com.oracle.truffle.espresso.shared/src/com/oracle/truffle/espresso/shared/constraints/LoadingConstraintsShared.java:254
if (!exists(c1.klass)) {
c1.klass = klass;
}
} else {
mergeConstraints(bucket, c1, c2);
}
}
}
private ConstraintBucket<Loader, Storage> lookup(Symbol<Type> type) {
return pairings.get(type);
}
private long checkConstraint(long klass, Constraint<Loader, Storage> c1) throws LoadingConstraintViolationException {
if (c1 != null) {
if (exists(c1.klass)) {
if (exists(klass)) {
if (klass != c1.klass) {
throw new LoadingConstraintViolationException("New loading constraint violates an older one!");
}
} else {
return c1.klass;
}
} else {
c1.klass = klass;
}
}
return klass;
}
private void mergeConstraints(ConstraintBucket<Loader, Storage> bucket, Constraint<Loader, Storage> c1, Constraint<Loader, Storage> c2) {
assert Thread.holdsLock(bucket);
Constraint<Loader, Storage> merge;
Constraint<Loader, Storage> delete;
if (c1.loaders.length < c2.loaders.length) {
merge = c2;
delete = c1;View on GitHub (pinned to a66e9ccd1d)
Solutions
- Ensure the type named in the failing constraint is loaded by a single common loader (or a common parent) across all loaders involved.
- Undeploy/drop the loader holding the stale class so the old constraint's class can be garbage-collected before reloading.
- Audit for duplicate jars/classes across deployment units and remove the duplicates.
- Wrap the triggering call in a catch of the resulting LinkageError and report which loader pair conflicted.
Defensive patterns
Strategy: try-catch
Try / catch
try {
reloadedOperation();
} catch (LinkageError e) {
if (e.getMessage() != null && e.getMessage().contains("violates an older one")) {
// old constraint still bound to a stale class: force context restart
scheduleContextRestart();
} else {
throw e;
}
} Prevention
- Avoid partial redeployments that leave old and new versions of a class loaded in sibling loaders.
- Design loader topology so constrained types resolve to one canonical class.
- Log the type symbol and loader pair when constraints fail to speed up classpath deduplication.
When it happens
Trigger: A second cross-loader operation reuses a Symbol<Type> whose constraint bucket already resolved to class A, while the new call site resolves the same name to class B (both loaded). Typical with several loaders resolving constrained method signatures inconsistently.
Common situations: Partial redeployment where one loader keeps the old class and a new loader loads an incompatible new version; duplicated classes across sibling loaders that later interact through constrained method calls.
Related errors
- Loading constraint violated !
- Class circularity detected
- Array type with more than 255 dimensions
- Method {}{} from type {} overrides final method {}{} from ty
- %s is not an enum type
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/21dc85d35f3981d6.
Report an issue: GitHub.