jenkinsci/jenkins · critical · IllegalStateException
Refusing to load the Jenkins test harness in production (via
Error message
Refusing to load the Jenkins test harness in production (via {}) What it means
IllegalStateException thrown by ClassicPluginStrategy.createClassLoader when a JAR on the plugin classpath has a name starting with 'jenkins-test-harness'. Jenkins deliberately refuses to load the test harness into a production controller because it pulls in test-only dependencies and assertions that break production behavior.
Source
Thrown at core/src/main/java/hudson/ClassicPluginStrategy.java:300
*/
@Deprecated(since = "2.459")
protected ClassLoader createClassLoader(List<File> paths, ClassLoader parent, Attributes atts) throws IOException {
// generate a legacy id so at least we can track to something
return createClassLoader("unidentified-" + UUID.randomUUID(), paths, parent, atts);
}
/**
* Creates a classloader that can load all the specified jar files and delegate to the given parent.
* @since 2.459
*/
protected ClassLoader createClassLoader(String name, List<File> paths, ClassLoader parent, Attributes atts) throws IOException {
boolean usePluginFirstClassLoader =
atts != null && Boolean.parseBoolean(atts.getValue("PluginFirstClassLoader"));
List<URL> urls = new ArrayList<>();
for (File path : paths) {
if (path.getName().startsWith("jenkins-test-harness")) {
throw new IllegalStateException("Refusing to load the Jenkins test harness in production (via "
+ atts.getValue("Short-Name") + ")");
}
urls.add(path.toURI().toURL());
}
URLClassLoader2 classLoader;
if (usePluginFirstClassLoader) {
classLoader = new PluginFirstClassLoader2(name, urls.toArray(new URL[0]), parent);
} else {
classLoader = new URLClassLoader2(name, urls.toArray(new URL[0]), parent);
}
return classLoader;
}
/**
* Computes the classloader that takes the class masking into account.
*
* <p>
* This mechanism allows plugins to have their own versions for libraries that core bundles.View on GitHub (pinned to 2e228ff40b)
Solutions
- Fix the plugin POM so jenkins-test-harness is test-scoped and excluded from the assembled .jpi (check the WEB-INF/lib of the packaged plugin).
- Remove the offending jenkins-test-harness-*.jar from the plugin archive and reinstall.
- Run 'mvn dependency:tree' on the plugin to find what transitively brings in the test harness and exclude it.
Example fix
<!-- before: scope leaked into the package --> <dependency> <groupId>org.jenkins-ci.main</groupId> <artifactId>jenkins-test-harness</artifactId> </dependency> <!-- after --> <dependency> <groupId>org.jenkins-ci.main</groupId> <artifactId>jenkins-test-harness</artifactId> <scope>test</scope> </dependency>
Defensive patterns
Strategy: validation
Validate before calling
// At build time, ensure no jenkins-test-harness jar is packaged
try (JarFile jf = new JarFile(pluginArchive)) {
if (jf.getEntry("WEB-INF/lib/jenkins-test-harness") != null
|| jf.stream().anyMatch(e -> e.getName().contains("jenkins-test-harness"))) {
throw new IllegalStateException("Plugin packages jenkins-test-harness; fix the POM");
}
} Try / catch
try {
strategy.createClassLoader(name, paths, parent, atts);
} catch (IllegalStateException e) {
if (e.getMessage().contains("jenkins-test-harness")) {
// reject the plugin build and fix dependency scoping
}
} Prevention
- Scope jenkins-test-harness as 'test' in plugin POMs.
- Run dependency:tree in CI to catch scope leakage.
- Inspect the packaged .jpi's WEB-INF/lib before release.
When it happens
Trigger: A plugin bundles (or its lib directory contains) jenkins-test-harness-*.jar as a dependency, so it ends up on the plugin's classpath at load time.
Common situations: Plugin build accidentally includes the test scope dependency in the packaged .jpi (scope leakage); a dependency pulled in transitively; a developer reused a fat-jar built with test classes.
Related errors
- Failed to load {}. The file does not exist
- Failed to load {}. It is not a file
- Failed to load {}
- Plugin installation failed. No manifest at {}
- {} doesn't extend from hudson.Plugin
AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14).
Data as JSON: /api/errors/f01d1147e29d789c.
Report an issue: GitHub.