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

  1. Examine the cause exception (getCause()) — CannotResolveClassException names the missing class; ConversionException describes the field and type mismatch.
  2. If a plugin was removed, either reinstall it or manually edit the config XML to remove references to the missing class.
  3. 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.
  4. If the XML is corrupt, restore from a backup (Jenkins keeps config backups in JENKINS_HOME with .bakN suffixes).
  5. 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

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


AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14). Data as JSON: /api/errors/14f94762c1f30cbe. Report an issue: GitHub.