OpenAPITools/openapi-generator · error · MojoExecutionException
Failed to write collapsed spec {0}
Error message
Failed to write collapsed spec {0} What it means
Thrown by ValidateMojo when <collapsedSpec> is configured: the resolved spec is serialized and written to {project.build.outputDirectory}/<collapsedSpec>.json|.yaml (normally target/classes), and an IOException — typically because target/classes does not exist yet, is unwritable, or the path is blocked — is wrapped in a MojoExecutionException whose message embeds the target path.
Source
Thrown at modules/openapi-generator-maven-plugin/src/main/java/org/openapitools/codegen/plugin/ValidateMojo.java:468
final var parseOptions = new ParseOptions();
parseOptions.setResolve(true);
final List<AuthorizationValue> authorizationValues = AuthParser.parse(this.auth);
final var openApiMerged = new OpenAPIResolver(
new OpenAPIV3Parser().readLocation(inputFile, authorizationValues, parseOptions).getOpenAPI()).resolve();
// Switch based on JSON or YAML.
final var extension = inputFile.toLowerCase(Locale.ROOT).endsWith(".json") ? ".json" : ".yaml";
final var mapper = inputFile.toLowerCase(Locale.ROOT).endsWith(".json") ? Json.mapper() : Yaml.mapper();
// Write the merged spec to the output file.
final var collapsedSpecPath =
Paths.get(project.getBuild().getOutputDirectory(), collapsedSpec + extension).toAbsolutePath();
try {
final var openApiString = mapper.writeValueAsString(openApiMerged);
FileUtils.writeStringToFile(collapsedSpecPath.toFile(), openApiString, StandardCharsets.UTF_8);
} catch (final IOException e) {
throw new MojoExecutionException(
new MessageFormat("Failed to write collapsed spec {0}", Locale.ROOT).format(collapsedSpecPath), e);
}
// Return the path to the collapsed spec file.
return collapsedSpecPath;
}
private void logInvalid(Invalid invalid) {
LOGLEVEL loglevel = invalid.getSeverity() == Severity.ERROR ? LOGLEVEL.ERROR : LOGLEVEL.WARNING;
loglevel.logColored(getLog(), invalid.getMessage());
loglevel.log(getLog(), MessageUtils.buffer().format("Based on rule: %s", invalid.getRule()).toString());
loglevel.log(getLog(), MessageUtils.buffer()
.format(isNotEmpty(invalid.getDetails()) ? "Details: %s" : "No details available.", invalid.getDetails())
.toString());
loglevel.logColored(getLog(), "----------");
}
private enum LOGLEVEL {View on GitHub (pinned to fcec517be3)
Solutions
- Pre-create the directory: bind the goal after a phase that creates target/classes (e.g. process-classes) or add a mkdir step/antrun execution beforehand.
- Check the path from the error message for a conflicting directory or lock and remove it.
- Ensure the build user can write to ${project.build.outputDirectory} (permissions, volume mount mode).
- If writing the collapsed spec during validation is unnecessary, remove <collapsedSpec>.
Example fix
<!-- before: bound to validate phase on clean checkout, target/classes missing --> <execution> <phase>validate</phase> <goals><goal>validate</goal></goals> <configuration><collapsedSpec>merged</collapsedSpec></configuration> </execution> <!-- after: bind later so target/classes exists --> <execution> <phase>process-classes</phase> <goals><goal>validate</goal></goals> <configuration><collapsedSpec>merged</collapsedSpec></configuration> </execution>
Defensive patterns
Strategy: validation
Validate before calling
# create target/classes before validating with collapsedSpec mkdir -p target/classes && mvn openapi-generator:validate
Prevention
- Bind the validate-with-collapse execution to a phase after compile (e.g. process-classes or test), when target/classes exists.
- On clean checkouts, add a mkdir/antrun step or rely on a later lifecycle phase instead of 'validate'.
- Keep ${project.build.outputDirectory} writable in containers/CI.
- Drop collapsedSpec from the validate goal unless the flattened artifact is actually consumed downstream.
When it happens
Trigger: Validate goal with <collapsedSpec>merged</collapsedSpec> running in a phase before target/classes exists (validate/init phases on a fresh checkout); read-only or containerized output directory; target path occupied by a directory; file locked by another process during the write.
Common situations: Binding validate+collapse to an early lifecycle phase so there is nothing in target/ yet; CI with cached/partially restored target directories; Docker volumes mounted read-only; IDE or antivirus locks on Windows.
Related errors
- Failed to write collapsed spec {0}
- Both %s and %s properties were set with different value.
- Helidon version %s uses the %s prefix for EE dependencies bu
- Error preparing constraint for version expression '{requeste
- Error parsing version expression '{requestedVersion}' as a v
AI-assisted analysis of OpenAPITools/openapi-generator@fcec517be3 (2026-08-22).
Data as JSON: /api/errors/875c0bac5982f8d8.
Report an issue: GitHub.