apache/maven · error · XmlWriterException

Unable to write model:

Error message

Unable to write model: 

What it means

Wrapper exception thrown by DefaultModelXmlFactory.write when serializing a Model fails for any reason: STaX writer errors (XMLStreamException), IOException while opening or writing the target path, or errors from the configured InputLocationFormatter. The original exception stays attached as the cause, and its message and location are appended to the wrapper text.

Source

Thrown at impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultModelXmlFactory.java:186

            Function<Object, String> formatter = request.getInputLocationFormatter();
            if (formatter != null) {
                xmlWriter.setAddLocationInformation(true);
                Function<InputLocation, String> adapter = formatter::apply;
                xmlWriter.setStringFormatter(adapter);
            }

            if (writer != null) {
                xmlWriter.write(writer, content);
            } else if (outputStream != null) {
                xmlWriter.write(outputStream, content);
            } else {
                try (OutputStream os = Files.newOutputStream(path)) {
                    xmlWriter.write(os, content);
                }
            }
        } catch (Exception e) {
            throw new XmlWriterException("Unable to write model: " + getMessage(e), getLocation(e), e);
        }
    }

    static class InputFactoryHolder {
        static final XMLInputFactory XML_INPUT_FACTORY;

        static {
            XMLInputFactory factory = XmlService.newXMLInputFactory();
            factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, true);
            factory.setProperty(XMLInputFactory.IS_COALESCING, true);
            XML_INPUT_FACTORY = factory;
        }
    }

    /**
     * Extracts the modelId (groupId:artifactId:version) from a POM XML stream
     * by parsing just enough XML to get the GAV coordinates.
     *

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Inspect getCause() on the XmlWriterException - it is almost always the real IOException or XMLStreamException
  2. For path targets, run Files.createDirectories(path.getParent()) before the write and verify the directory is writable
  3. If an InputLocationFormatter is set, test it separately; a throwing formatter surfaces here too
  4. Verify a STaX implementation (JDK built-in or Woodstox) is on the classpath

Example fix

// before
modelXmlFactory.write(XmlWriterRequest.builder()
    .content(model)
    .path(target)
    .build()); // NoSuchFileException if parent dir missing

// after
Files.createDirectories(target.getParent());
modelXmlFactory.write(XmlWriterRequest.builder()
    .content(model)
    .path(target)
    .build());
Defensive patterns

Strategy: try-catch

Try / catch

try {
    modelXmlFactory.write(req);
} catch (XmlWriterException e) {
    Throwable cause = e.getCause();
    if (cause instanceof IOException io) {
        // target not writable, missing directory, disk full
    } else if (cause instanceof XMLStreamException xs) {
        // content not serializable as XML
    }
}

Prevention

When it happens

Trigger: Writing to a Path whose parent directory does not exist or is not writable; XMLStreamWriter failures from the STaX implementation; a Model whose content cannot be serialized; an InputLocationFormatter that throws while producing location strings.

Common situations: Writing pom.xml into a directory that was never created; read-only checkouts in CI; a classpath without a working STaX implementation; custom location formatters that assume non-null InputLocation.

Related errors


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