apache/maven · error · IllegalArgumentException

writer or outputStream must be non null

Error message

writer or outputStream must be non null

What it means

DefaultToolchainsXmlFactory.write accepts only a Writer or an OutputStream; there is no path support. If both are null the call is rejected with IllegalArgumentException before serialization starts.

Source

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

            xml.setAddDefaultEntities(request.isAddDefaultEntities());
            if (reader != null) {
                return xml.read(reader, request.isStrict(), source);
            } else {
                return xml.read(inputStream, request.isStrict(), source);
            }
        } catch (Exception e) {
            throw new XmlReaderException("Unable to read toolchains: " + getMessage(e), getLocation(e), e);
        }
    }

    @Override
    public void write(XmlWriterRequest<PersistedToolchains> request) throws XmlWriterException {
        requireNonNull(request, "request");
        PersistedToolchains content = Objects.requireNonNull(request.getContent(), "content");
        OutputStream outputStream = request.getOutputStream();
        Writer writer = request.getWriter();
        if (writer == null && outputStream == null) {
            throw new IllegalArgumentException("writer or outputStream must be non null");
        }
        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) {

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Use .writer(...) or .outputStream(...) on the request
  2. For file output, open the stream yourself: .outputStream(Files.newOutputStream(path)) inside try-with-resources
  3. For in-memory output use .writer(new StringWriter())

Example fix

// before
toolchainsXmlFactory.write(XmlWriterRequest.builder()
    .content(toolchains)
    .path(toolchainsPath) // no path support on this factory
    .build()); // throws

// after
try (OutputStream os = Files.newOutputStream(toolchainsPath)) {
    toolchainsXmlFactory.write(XmlWriterRequest.builder()
        .content(toolchains)
        .outputStream(os)
        .build());
}
Defensive patterns

Strategy: validation

Validate before calling

XmlWriterRequest<PersistedToolchains> req = XmlWriterRequest.builder()
    .content(toolchains)
    .build();
if (req.getWriter() == null && req.getOutputStream() == null) {
    throw new IllegalStateException("toolchains write request has no writer or outputStream");
}
toolchainsXmlFactory.write(req);

Prevention

When it happens

Trigger: Building a write request for PersistedToolchains with only .path(...) set (ignored here), or with no output target at all.

Common situations: Porting code from the model factory's path-based write; tests that set only the content.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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