apache/maven · error · XmlWriterException

Unable to write plugin:

Error message

Unable to write plugin: 

What it means

Wrapper thrown by DefaultPluginXmlFactory.write when serializing a PluginDescriptor fails: STaX writer errors or IOException while opening and writing the target path. The real failure is preserved as the cause and its message and location are appended.

Source

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

        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);
            } else {
                try (OutputStream os = Files.newOutputStream(path)) {
                    new PluginDescriptorStaxWriter().write(os, content);
                }
            }
        } catch (Exception e) {
            throw new XmlWriterException("Unable to write plugin: " + getMessage(e), getLocation(e), e);
        }
    }

    /**
     * Simply parse the given xml string.
     *
     * @param xml the input XML string
     * @return the parsed object
     * @throws XmlReaderException if an error occurs during the parsing
     * @see #toXmlString(Object)
     */
    public static PluginDescriptor fromXml(@Nonnull String xml) throws XmlReaderException {
        return new DefaultPluginXmlFactory().fromXmlString(xml);
    }

    /**
     * Simply converts the given content to an XML string.
     *

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Unwrap getCause() to see the actual IOException or XMLStreamException
  2. Run Files.createDirectories(path.getParent()) before the write
  3. Verify write permission on the target directory in the failing environment

Example fix

// before
pluginXmlFactory.write(XmlWriterRequest.builder()
    .content(descriptor)
    .path(outputDir.resolve("plugin.xml"))
    .build());

// after
Files.createDirectories(outputDir);
pluginXmlFactory.write(XmlWriterRequest.builder()
    .content(descriptor)
    .path(outputDir.resolve("plugin.xml"))
    .build());
Defensive patterns

Strategy: try-catch

Try / catch

try {
    pluginXmlFactory.write(req);
} catch (XmlWriterException e) {
    if (e.getCause() instanceof IOException io) {
        // create parent directories / fix permissions, then retry once
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Writing a descriptor to a path whose parent directory does not exist or is not writable; XMLStreamWriter failures; disk-full conditions during the write.

Common situations: Regenerating plugin.xml into a build output directory that does not exist yet; read-only source trees in CI sandboxes.

Related errors


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