jenkinsci/jenkins · error · IOException
Unable to read {}
Error message
Unable to read {} What it means
Thrown by XmlFile.read() — which loads an XML file into a new object via XStream (xs.fromXML). Any RuntimeException or Error during deserialization is caught and wrapped in an IOException with the file path. This is the path for reading a config file fresh (not into an existing object).
Source
Thrown at core/src/main/java/hudson/XmlFile.java:167
public File getFile() {
return file;
}
public XStream getXStream() {
return xs;
}
/**
* Loads the contents of this file into a new object.
*/
public Object read() throws IOException {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Reading " + file);
}
try (InputStream in = new BufferedInputStream(Files.newInputStream(file.toPath()))) {
return xs.fromXML(in);
} catch (RuntimeException | Error e) {
throw new IOException("Unable to read " + file, e);
}
}
/**
* Loads the contents of this file into an existing object.
*
* @return
* The unmarshalled object. Usually the same as {@code o}, but would be different
* if the XML representation is completely new.
*/
public Object unmarshal(Object o) throws IOException {
return unmarshal(o, false);
}
/**
* Variant of {@link #unmarshal(Object)} applying {@link XStream2#unmarshal(HierarchicalStreamReader, Object, DataHolder, boolean)}.
* @since 2.99
*/View on GitHub (pinned to 2e228ff40b)
Solutions
- Examine the cause exception (getCause()) — CannotResolveClassException names the missing class; ConversionException describes the field and type mismatch.
- If a plugin was removed, either reinstall it or manually edit the config XML to remove references to the missing class.
- If a class was renamed, add an XStream alias mapping in the plugin's XStream configuration or update the XML to use the new class name.
- If the XML is corrupt, restore from a backup (Jenkins keeps config backups in JENKINS_HOME with .bakN suffixes).
- For NoClassDefFoundError, ensure the plugin's dependencies are installed at compatible versions.
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate file is readable and non-empty before deserialization
if (!file.exists() || file.length() == 0) {
throw new IOException("Config file missing or empty: " + file);
} Try / catch
try {
Object result = xmlFile.read();
} catch (IOException e) {
Throwable cause = e.getCause();
if (cause instanceof CannotResolveClassException) {
// A class referenced in XML is not on classpath
LOGGER.severe("Unknown class in config: " + cause.getMessage());
} else if (cause instanceof ConversionException) {
LOGGER.severe("Type mismatch in config: " + cause.getMessage());
}
// Optionally restore from backup
} Prevention
- Never uninstall plugins without cleaning their config files that reference plugin classes.
- Keep config.xml backups (Jenkins does this automatically with .bak suffixes).
- Test plugin upgrades in a staging instance before applying to production.
When it happens
Trigger: xs.fromXML(in) throws a RuntimeException — common XStream exceptions include CannotResolveClassException (class referenced in XML not on classpath), ForbiddenFieldException, or ConversionException (field type mismatch, invalid enum value, etc.). An Error (e.g., NoClassDefFoundError) is also caught and wrapped.
Common situations: A plugin was uninstalled or renamed, so classes referenced in config.xml can no longer be resolved; XStream annotations or converters changed between versions; config.xml is hand-edited with invalid XML structure or invalid enum values; a class was refactored (renamed/moved) but old XML references the old class name; NoClassDefFoundError from a missing transitive dependency.
Related errors
- Failed to detect encoding of {}
- remote file operation failed
- Malformed plugin attribute: {0}
- Failed to parse XML
AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14).
Data as JSON: /api/errors/14f94762c1f30cbe.
Report an issue: GitHub.