{"record":{"id":"192dbe1d7929c2d6","repo":"OpenAPITools/openapi-generator","slug":"choose-between-spring-boot-3-and-spring-boot-4","errorCode":null,"errorMessage":"Choose between Spring Boot 3 and Spring Boot 4","messagePattern":"Choose between Spring Boot 3 and Spring Boot 4","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java","lineNumber":847,"sourceCode":"        writePropertyBack(AUTO_X_SPRING_PAGINATED, autoXSpringPaginated);\n        if (additionalProperties.containsKey(GENERATE_SORT_VALIDATION) && library.equals(SPRING_BOOT)) {\n            this.setGenerateSortValidation(convertPropertyToBoolean(GENERATE_SORT_VALIDATION));\n        }\n        writePropertyBack(GENERATE_SORT_VALIDATION, generateSortValidation);\n        if (additionalProperties.containsKey(GENERATE_PAGEABLE_CONSTRAINT_VALIDATION) && library.equals(SPRING_BOOT)) {\n            this.setGeneratePageableConstraintValidation(convertPropertyToBoolean(GENERATE_PAGEABLE_CONSTRAINT_VALIDATION));\n        }\n        writePropertyBack(GENERATE_PAGEABLE_CONSTRAINT_VALIDATION, generatePageableConstraintValidation);\n        if (additionalProperties.containsKey(SUBSTITUTE_GENERIC_PAGED_MODEL)) {\n            this.setSubstituteGenericPagedModel(convertPropertyToBoolean(SUBSTITUTE_GENERIC_PAGED_MODEL));\n        }\n        writePropertyBack(SUBSTITUTE_GENERIC_PAGED_MODEL, substituteGenericPagedModel);\n        if (additionalProperties.containsKey(CodegenConstants.USE_ENUM_VALUE_INTERFACE)) {\n            this.setUseEnumValueInterface(convertPropertyToBoolean(CodegenConstants.USE_ENUM_VALUE_INTERFACE));\n        }\n        writePropertyBack(CodegenConstants.USE_ENUM_VALUE_INTERFACE, useEnumValueInterface);\n        if (isUseSpringBoot3() && isUseSpringBoot4()) {\n            throw new IllegalArgumentException(\"Choose between Spring Boot 3 and Spring Boot 4\");\n        }\n\n        if (isUseJackson3() && !isUseSpringBoot4()) {\n            throw new IllegalArgumentException(\"useJackson3 is only available with Spring Boot >= 4\");\n        }\n\n        if (additionalProperties.containsKey(CodegenConstants.OPENAPI_NULLABLE)) {\n            this.setOpenApiNullable(convertPropertyToBoolean(CodegenConstants.OPENAPI_NULLABLE));\n        }\n        writePropertyBack(CodegenConstants.OPENAPI_NULLABLE, openApiNullable);\n\n        if (isUseSpringBoot3() || isUseSpringBoot4()) {\n            if (AnnotationLibrary.SWAGGER1.equals(getAnnotationLibrary())) {\n                throw new IllegalArgumentException(AnnotationLibrary.SWAGGER1.getPropertyName() + \" is not supported with Spring Boot > 3.x\");\n            }\n            useJakartaEe = true;\n            additionalProperties.put(USE_JAKARTA_EE, useJakartaEe);\n            applyJakartaPackage();","sourceCodeStart":829,"sourceCodeEnd":865,"githubUrl":"https://github.com/OpenAPITools/openapi-generator/blob/fcec517be3cf5b7964296bcba25fbc97541484e7/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java#L829-L865","documentation":"kotlin-spring has mutually exclusive Spring Boot major-version switches. If both useSpringBoot3 and useSpringBoot4 resolve to true after option processing, processOpts() throws 'Choose between Spring Boot 3 and Spring Boot 4' (KotlinSpringServerCodegen.java:847). Each flag is only defaulted when not set, so this fires only when both are explicitly true in the same invocation.","triggerScenarios":"Passing `--additional-properties useSpringBoot3=true,useSpringBoot4=true` in one command, or setting both <useSpringBoot3>true</useSpringBoot3> and <useSpringBoot4>true</useSpringBoot4> in the Maven/Gradle plugin configOptions block.","commonSituations":"Appending version flags during a Boot 3 → Boot 4 migration without removing the old one; build scripts that concatenate a base options map with override options; documentation examples updated to Boot 4 while the user's script still adds useSpringBoot3.","solutions":["Keep exactly one version flag: remove `useSpringBoot3=true` and keep `useSpringBoot4=true` (or vice versa).","In shared build logic, make the Boot version a single variable that expands to one flag instead of two independent booleans.","After the fix, verify only one of useSpringBoot3/useSpringBoot4 appears in the generated pom/build files."],"exampleFix":"# before\nopenapi-generator-cli generate -g kotlin-spring -i api.yaml \\\n  --additional-properties useSpringBoot3=true,useSpringBoot4=true\n# after\nopenapi-generator-cli generate -g kotlin-spring -i api.yaml \\\n  --additional-properties useSpringBoot4=true","handlingStrategy":"validation","validationCode":"boolean sb3 = Boolean.parseBoolean(String.valueOf(opts.getOrDefault(\"useSpringBoot3\", \"false\")));\nboolean sb4 = Boolean.parseBoolean(String.valueOf(opts.getOrDefault(\"useSpringBoot4\", \"false\")));\nif (sb3 && sb4) {\n    throw new IllegalArgumentException(\"Set only one of useSpringBoot3 / useSpringBoot4\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    new DefaultGenerator().opts(clientOptInput).generate();\n} catch (IllegalArgumentException e) {\n    throw new BuildException(\"Invalid kotlin-spring options: \" + e.getMessage(), e);\n}","preventionTips":["Model the Boot major version as a single choice (e.g. springBootMajor=4) that expands to one flag.","During Boot migrations, delete the old flag in the same commit that adds the new one.","Assert on the generated pom.gradle dependencies to confirm which Boot version was targeted."],"tags":["kotlin","spring","spring-boot","version-conflict","option-combination","openapi-generator","config-validation"],"backgroundTag":"incompatible-option-combination","analyzedSha":"fcec517be3cf5b7964296bcba25fbc97541484e7","analyzedAt":"2026-08-22T11:13:11.613Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}