apache/maven · error · XmlWriterException

Unable to write toolchains: {}

Error message

Unable to write toolchains: {}

What it means

Thrown by ToolchainsXmlFactory.write (DefaultToolchainsXmlFactory) when serializing a PersistedToolchains model to XML fails. The method wraps every exception raised by the StAX writer while writing to the supplied Writer/OutputStream, and appends the underlying cause's message to 'Unable to write toolchains: '. Typical root causes are I/O failures (read-only or missing output path, closed stream, disk full) or a model containing values the toolchains writer cannot serialize.

Source

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

        }
        try {
            MavenToolchainsStaxWriter xmlWriter = new MavenToolchainsStaxWriter();
            xmlWriter.setAddLocationInformation(false);

            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 {
                xmlWriter.write(outputStream, content);
            }
        } catch (Exception e) {
            throw new XmlWriterException("Unable to write toolchains: " + getMessage(e), getLocation(e), e);
        }
    }
}

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Read the appended cause message and inspect XmlWriterException.getCause() to distinguish IOException (output target problem) from a model/serialization problem
  2. Verify the output file is writable and the stream/writer is still open before calling write
  3. Round-trip the model: read toolchains with the same factory, modify the result, and write it back instead of constructing PersistedToolchains by hand
  4. Ensure every Toolchain entry has a non-null type and a non-null parameters map before writing

Example fix

// before: hand-built model, closed stream
PersistedToolchains tc = new PersistedToolchains();
tc.addToolchain(new Toolchain(null, null)); // null type
factory.write(XmlWriterRequest.builder().content(tc).outputStream(closedOut).build());

// after: round-trip a valid model to a writable target
PersistedToolchains tc = factory.read(XmlReaderRequest.builder().path(toolchainsPath).build());
tc.getToolchains().get(0).getParameters().put("jdk", "17");
try (OutputStream out = Files.newOutputStream(toolchainsPath)) {
    factory.write(XmlWriterRequest.builder().content(tc).outputStream(out).build());
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before writing toolchains
Path out = toolchainsPath;
if (!Files.isWritable(out.getParent() == null ? Path.of(".") : out.getParent())) {
    throw new IllegalStateException("toolchains output directory not writable: " + out);
}
for (Toolchain tc : content.getToolchains()) {
    Objects.requireNonNull(tc.getType(), "toolchain type");
    Objects.requireNonNull(tc.getParameters(), "toolchain parameters");
}

Try / catch

try {
    toolchainsXmlFactory.write(request);
} catch (XmlWriterException e) {
    Throwable cause = e.getCause();
    if (cause instanceof IOException io) {
        // output target problem: permissions, closed stream, disk full
        throw new IllegalStateException("Cannot write toolchains to target: " + io.getMessage(), e);
    }
    throw e; // model/serialization problem: fix the content
}

Prevention

When it happens

Trigger: Calling ToolchainsXmlFactory.write(XmlWriterRequest) with an OutputStream/Writer that is closed or targets a read-only file; passing a hand-built PersistedToolchains whose toolchain entries contain null type or null parameters; disk exhaustion during the write.

Common situations: Programmatic editing of ~/.m2/toolchains.xml through the Maven API where the model was assembled manually instead of round-tripped; CI agents with full disks; writing to a directory the process does not own; a partially-populated model after a failed read-modify-write cycle.

Related errors


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