OpenAPITools/openapi-generator · error · RuntimeException
Cannot merge specs that declare incompatible OpenAPI version
Error message
Cannot merge specs that declare incompatible OpenAPI versions %s. All specs must share the same major.minor version (e.g. all 3.0.x or all 3.1.x); mixing 3.0 and 3.1 is not supported because version-specific fields and semantics are not translated.
What it means
After well-formedness checks, resolveOutputVersion() compares every source's major.minor against the first spec's; any divergence throws with the distinct version list. Merging across major.minor lines (3.0.x with 3.1.x) is unsupported because version-specific fields and semantics are not translated. The merged output declares the highest patch version among sources once this check passes.
Source
Thrown at modules/openapi-generator/src/main/java/org/openapitools/codegen/config/MergedSpecBuilder.java:545
if (versions.stream().anyMatch(Objects::isNull)) {
throw new RuntimeException(
"Cannot merge specs where some declare an OpenAPI version and others do not. The 'openapi' "
+ "field is required; every source spec must declare a version so compatibility can be verified.");
}
// Reject malformed versions before comparing, so a value like '3.x.3' cannot pass the
// major.minor check by having its non-numeric segment normalized to zero.
for (String version : versions) {
if (!isWellFormedVersion(version)) {
throw new RuntimeException(String.format(Locale.ROOT,
"Malformed OpenAPI version '%s' in a source spec. Expected exactly three numeric "
+ "components (MAJOR.MINOR.PATCH) without leading zeroes, such as '3.0.3' or '3.1.0'.",
version));
}
}
String firstMajorMinor = majorMinor(versions.get(0));
for (String version : versions) {
if (!majorMinor(version).equals(firstMajorMinor)) {
throw new RuntimeException(String.format(Locale.ROOT,
"Cannot merge specs that declare incompatible OpenAPI versions %s. All specs must share "
+ "the same major.minor version (e.g. all 3.0.x or all 3.1.x); mixing 3.0 and 3.1 "
+ "is not supported because version-specific fields and semantics are not translated.",
versions.stream().distinct().collect(Collectors.toList())));
}
}
// Same major.minor across all specs — declare the highest patch version encountered.
String highest = versions.get(0);
for (String version : versions) {
if (compareVersions(version, highest) > 0) {
highest = version;
}
}
return highest;
}
/**
* Returns {@code true} if {@code version} is a well-formed OpenAPI version: exactly three ASCIIView on GitHub (pinned to fcec517be3)
Solutions
- Upgrade or downgrade all source specs to one major.minor line (convert 3.0 specs to 3.1, or the reverse) before merging.
- If a spec only differs in patch (3.0.1 vs 3.0.3), align them anyway for clean output — though patches already merge to the highest.
- Split the merge into two runs, one per version line, if migration must be staged.
- Use a converter (e.g. swagger-converter / openapi-diff tooling) to bring stragglers onto the chosen line.
Example fix
# before pet.yaml: openapi: 3.0.1 store.yaml: openapi: 3.1.0 # after (align all to one line) pet.yaml: openapi: 3.1.0 store.yaml: openapi: 3.1.0
Defensive patterns
Strategy: validation
Validate before calling
// All specs must share one major.minor before merging
Set<String> majorMinor = specFiles.stream()
.map(f -> readOpenapiField(f))
.filter(Objects::nonNull)
.map(v -> v.substring(0, v.lastIndexOf('.')))
.collect(Collectors.toSet());
if (majorMinor.size() > 1) throw new IllegalArgumentException("Mixed versions: " + majorMinor); Try / catch
Catch RuntimeException containing "incompatible OpenAPI versions"; print the distinct version set, then route specs into per-version merge runs or convert them.
Prevention
- Standardize one OpenAPI line (e.g. all 3.0.x) in your spec repository guidelines.
- Gate merges on a version-homogeneity check in CI.
- When starting a 3.1 migration, convert the whole catalog in one commit rather than gradually.
When it happens
Trigger: Merging pet.yaml (openapi: 3.0.1) with store.yaml (openapi: 3.1.0); introducing a newly-authored 3.1 spec (for e.g. nullable/examples changes) into an existing 3.0 catalog.
Common situations: Gradual 3.0→3.1 migrations where some teams converted early; mixed tooling emitting different default versions; pulling third-party specs with a different baseline into an internal merge.
Related errors
- Cannot merge specs where some declare an OpenAPI version and
- inputSpecFiles list is empty — nothing to merge
- Spec directory doesn't contain any specification
- No valid specifications found to merge
- Failed to serialize merged spec
AI-assisted analysis of OpenAPITools/openapi-generator@fcec517be3 (2026-08-22).
Data as JSON: /api/errors/07124f293531d914.
Report an issue: GitHub.