jenkinsci/jenkins · error · LinkageError
Failed to resolve ${c}
Error message
Failed to resolve ${c} What it means
Thrown by GuiceExtensionResolver.resolve(Class) when introspecting an extension class's @Inject fields, methods, and constructors raises a RuntimeException. Jenkins deliberately converts this to a LinkageError because a class that cannot have its injectable members resolved is effectively missing a dependency. The original RuntimeException is the cause.
Source
Thrown at core/src/main/java/hudson/ExtensionFinder.java:557
method.getAnnotatedParameterTypes();
method.getParameterAnnotations();
}
}
// See com.google.inject.spi.InjectionPoint(TypeLiteral, Field, boolean)
for (Field f : cc.getDeclaredFields()) {
if (f.isAnnotationPresent(javax.inject.Inject.class)
|| f.isAnnotationPresent(jakarta.inject.Inject.class)
|| f.isAnnotationPresent(com.google.inject.Inject.class)) {
f.getAnnotations();
f.getAnnotatedType().getAnnotations();
resolve(f.getType(), encountered);
}
}
}
LOGGER.log(Level.FINER, "{0} looks OK", c);
} catch (RuntimeException x) {
throw new LinkageError("Failed to resolve " + c, x);
}
}
@SuppressWarnings({"unchecked", "ChainOfInstanceofChecks"})
@Override
protected void configure() {
bindListener(Matchers.any(), this);
for (final IndexItem<?, Object> item : index) {
boolean optional = isOptional(item.annotation());
try {
AnnotatedElement e = item.element();
Annotation a = item.annotation();
if (!isActive(a, e)) continue;
Scope scope = optional ? QUIET_FAULT_TOLERANT_SCOPE : FAULT_TOLERANT_SCOPE;
if (e instanceof Class) {View on GitHub (pinned to 2e228ff40b)
Solutions
- Inspect the cause: NoClassDefFoundError/TypeNotPresentException names the missing type.
- Install or upgrade the plugin/library that provides the missing class.
- If the field is truly optional, remove @Inject or mark the extension optional in the index (@Optional).
- Rebuild the plugin to align compile-time and runtime dependencies.
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
try {
// trigger Guice extension resolution
} catch (LinkageError e) {
// 'Failed to resolve' — read cause for the missing type
if (e.getCause() instanceof NoClassDefFoundError) { /* install missing dependency */ }
else throw e;
} Prevention
- Keep plugin dependency versions aligned with compile-time in pom.xml.
- Mark truly optional @Inject points optional, or remove @Inject if the type may be absent.
- Run a smoke boot in a clean environment after dependency changes.
When it happens
Trigger: An @Inject field/method/constructor references a type whose class is missing or fails to load; a reflection call (getDeclaredFields/getDeclaredMethods) throws for a malformed class; resolve(f.getType()) triggers a NoClassDefFoundError or TypeNotPresentException during Guice binding setup.
Common situations: Plugin missing a transitive dependency jar; class compiled against an API version not present at runtime; optional dependency that is actually required by an @Inject field; class file corruption causing reflection to throw.
Related errors
AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14).
Data as JSON: /api/errors/ab7597f5cfaba90a.
Report an issue: GitHub.