apache/maven · error · XmlReaderException

Unable to read plugin:

Error message

Unable to read plugin: 

What it means

Wrapper thrown when parsing a PluginDescriptor (plugin.xml) fails: malformed XML, strict-mode rejection of unknown elements, or IO errors while opening the path or URL. The underlying exception is preserved as the cause; STaX causes carry line and column information which the factory appends to the message.

Source

Thrown at impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultPluginXmlFactory.java:77

            PluginDescriptorStaxReader xml = request.getTransformer() != null
                    ? new PluginDescriptorStaxReader(request.getTransformer()::transform)
                    : new PluginDescriptorStaxReader();
            xml.setAddDefaultEntities(request.isAddDefaultEntities());
            if (inputStream != null) {
                return xml.read(inputStream, request.isStrict());
            } else if (reader != null) {
                return xml.read(reader, request.isStrict());
            } else if (path != null) {
                try (InputStream is = Files.newInputStream(path)) {
                    return xml.read(is, request.isStrict());
                }
            } else {
                try (InputStream is = url.openStream()) {
                    return xml.read(is, request.isStrict());
                }
            }
        } catch (Exception e) {
            throw new XmlReaderException("Unable to read plugin: " + getMessage(e), getLocation(e), e);
        }
    }

    @Override
    public void write(XmlWriterRequest<PluginDescriptor> request) throws XmlWriterException {
        requireNonNull(request, "request");
        PluginDescriptor content = requireNonNull(request.getContent(), "content");
        Path path = request.getPath();
        OutputStream outputStream = request.getOutputStream();
        Writer writer = request.getWriter();
        if (writer == null && outputStream == null && path == null) {
            throw new IllegalArgumentException("writer, outputStream or path must be non null");
        }
        try {
            if (writer != null) {
                new PluginDescriptorStaxWriter().write(writer, content);
            } else if (outputStream != null) {
                new PluginDescriptorStaxWriter().write(outputStream, content);

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Read getCause() - XMLStreamException messages include the line and column of the failure
  2. Set .strict(false) on the request when unknown elements are expected and tolerable
  3. Validate the descriptor XML externally (xmllint) before passing it in
  4. For URL sources, fetch and inspect what the server actually returns before parsing

Example fix

// before
PluginDescriptor pd = pluginXmlFactory.read(XmlReaderRequest.builder()
    .path(descriptorPath)
    .build()); // strict default may reject unknown tags

// after
PluginDescriptor pd = pluginXmlFactory.read(XmlReaderRequest.builder()
    .path(descriptorPath)
    .strict(false)
    .build());
Defensive patterns

Strategy: try-catch

Try / catch

try {
    PluginDescriptor pd = pluginXmlFactory.read(req);
} catch (XmlReaderException e) {
    Throwable cause = e.getCause();
    // XMLStreamException: line/column of parse failure; IOException: unreadable source
    log.error("plugin.xml invalid: {} at {}", e.getMessage(), e.getLocation(), cause);
}

Prevention

When it happens

Trigger: Feeding a malformed or truncated plugin.xml; strict mode active while the descriptor contains elements unknown to the bundled descriptor model; an unreadable path or a URL whose openStream() fails.

Common situations: Reading plugin descriptors generated by a different maven-plugin-tools version than the runtime model expects; descriptors corrupted during packaging; URL sources behind proxies that return error pages instead of XML.

Related errors


AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21). Data as JSON: /api/errors/51cfbf2e9209e363. Report an issue: GitHub.