OpenAPITools/openapi-generator · error · RuntimeException
Cannot merge specs where some declare an OpenAPI version…
Error message
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.
What it means
MergedSpecBuilder.resolveOutputVersion() collects each source spec's `openapi` field. If at least one spec declares a version and at least one does not, merging is refused: an unversioned source cannot be assumed compatible with a versioned one, and the code refuses to guess. Only when every source is unversioned does it fall back to the default '3.0.3'. This is a deliberate strictness change — the required-ness of `openapi` is enforced at merge time.
Solutions
- Add an explicit `openapi: <version>` field to every source spec in the merge set, matching the others' major.minor.
- Alternatively remove the field from all sources so the 3.0.3 default applies — only valid if the specs are genuinely 3.0.x-compatible.
- Validate with a pre-merge lint rule that every file has an `openapi` key.
Example fix
# before (fragments.yaml) components: parameters: ... # after openapi: 3.0.3 components: parameters: ...
Defensive patterns
Strategy: validation
Validate before calling
// Every spec must declare an openapi version before merge
for (String f : specFiles) {
JsonNode n = new ObjectMapper(new YAMLFactory()).readTree(new File(f));
if (n.get("openapi") == null || n.get("openapi").asText().isBlank()) {
throw new IllegalArgumentException(f + " is missing the required 'openapi' field");
}
} Try / catch
Catch RuntimeException with "Cannot merge specs where some declare"; list which inputs lack the openapi field and stop for manual fix.
Prevention
- Make 'openapi' a required key in your spec lint/CI schema.
- Template new fragment files with the version header pre-filled.
When it happens
Trigger: Merging pet.yaml (openapi: 3.0.1) with fragments.yaml (no openapi field, e.g. a shared parameters/components file); adding a new component-only file without a version header to an existing versioned catalog.
Common situations: Spec catalogs where common fragments were never given `openapi` because individual generators tolerated it; converting multi-file Swagger 2.0-era catalogs; teams introducing new partial specs after a merge pipeline already exists.
Related errors
- Cannot merge specs that declare incompatible OpenAPI…
- Component name conflict during spec merge: ' ' is defined…
- Exception while listing files in spec root directory
- Failed to serialize merged spec
- inputSpecFiles list is empty — nothing to merge
AI-assisted analysis of OpenAPITools/openapi-generator@fcec517be3 (2026-08-22).
Data as JSON: /api/errors/e19173cb41b0ca80.
Report an issue: GitHub.
Appendix: source
Thrown at modules/openapi-generator/src/main/java/org/openapitools/codegen/config/MergedSpecBuilder.java:528
* unversioned. Malformed version strings (non-numeric segments such as {@code 3.x.3}) are
* rejected outright.</p>
*
* @throws RuntimeException if the sources declare different major.minor OpenAPI versions, mix
* versioned and unversioned specs, or contain a malformed version
*/
private String resolveOutputVersion(List<OpenAPI> specs) {
List<String> versions = specs.stream()
.map(OpenAPI::getOpenapi)
.collect(Collectors.toList());
if (versions.stream().noneMatch(Objects::nonNull)) {
// Every source is unversioned — fall back to the default.
return "3.0.3";
}
// At least one source declares a version. Since 'openapi' is required, an unversioned
// source cannot be assumed compatible and must not be silently accepted.
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 "View on GitHub (pinned to fcec517be3)