diff --git a/docs/generators/kotlin.md b/docs/generators/kotlin.md
index a6268f931aa4..813ea5918b7a 100644
--- a/docs/generators/kotlin.md
+++ b/docs/generators/kotlin.md
@@ -25,6 +25,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|companionObject|Whether to generate companion objects in data classes, enabling companion extensions.| |false|
|dateLibrary|Option. Date library to use|
- **threetenbp-localdatetime**
- Threetenbp - Backport of JSR310 (jvm only, for legacy app only)
- **kotlinx-datetime**
- kotlinx-datetime (preferred for multiplatform)
- **string**
- String
- **java8-localdatetime**
- Java 8 native JSR310 (jvm only, for legacy app only)
- **java8**
- Java 8 native JSR310 (jvm only, preferred for jdk 1.8+)
- **threetenbp**
- Threetenbp - Backport of JSR310 (jvm only, preferred for jdk < 1.8)
|java8|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', 'original', and 'bestEffortBacktick' (like 'original' but tries to wrap values in backticks before falling back to sanitizing, e.g. `name,asc` stays `name,asc` rather than becoming nameCommaAsc; useful for sort/order enums)| |original|
+|enumUnknownDefaultCase|Add an `unknown_default_open_api` enum case as a fallback for unrecognized values. Only `moshi`(serializationLibrary) decodes every unknown value to it: `jackson` skips nullable enums, `kotlinx_serialization` skips non-string enums, and neither `gson`(serializationLibrary) nor `multiplatform`(library) decodes to it at all.|- **false**
- No changes to the enums are made, this is the default option.
- **true**
- Each enum gains an `unknown_default_open_api` case.
|false|
|explicitApi|Generates code with explicit access modifiers to comply with Kotlin Explicit API Mode.| |false|
|failOnUnknownProperties|Fail Jackson de-serialization on unknown properties| |false|
|generateOneOfAnyOfWrappers|Generate oneOf, anyOf schemas as wrappers. Only `jvm-retrofit2`(library) with `gson` or `kotlinx_serialization`(serializationLibrary) support this option.| |false|
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java
index 3898d9a9dc88..90b3c8ad9bcf 100755
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java
@@ -316,6 +316,19 @@ public KotlinClientCodegen() {
cliOptions.add(CliOption.newBoolean(USE_RESPONSE_AS_RETURN_TYPE, "When using retrofit2 and coroutines, use `Response`<`T`> as return type instead of `T`.", true));
cliOptions.add(CliOption.newBoolean(USE_JACKSON_3, "Use Jackson 3 dependencies (tools.jackson package). Requires serializationLibrary=jackson. Incompatible with openApiNullable."));
+
+ // AbstractKotlinCodegen calls cliOptions.clear(), dropping DefaultCodegen's registration.
+ // Re-registered on kotlin alone: no other Kotlin generator's templates implement the fallback.
+ CliOption enumUnknownDefaultCaseOpt = CliOption.newBoolean(
+ CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE,
+ "Add an `unknown_default_open_api` enum case as a fallback for unrecognized values. Only `moshi`(serializationLibrary) decodes every unknown value to it: `jackson` skips nullable enums, `kotlinx_serialization` skips non-string enums, and neither `gson`(serializationLibrary) nor `multiplatform`(library) decodes to it at all.");
+ Map enumUnknownDefaultCaseOpts = new HashMap<>();
+ enumUnknownDefaultCaseOpts.put("false",
+ "No changes to the enums are made, this is the default option.");
+ enumUnknownDefaultCaseOpts.put("true",
+ "Each enum gains an `unknown_default_open_api` case.");
+ enumUnknownDefaultCaseOpt.setEnum(enumUnknownDefaultCaseOpts);
+ cliOptions.add(enumUnknownDefaultCaseOpt);
}
@Override
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java
index 921cd035aeb4..dad52b7ae72b 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java
@@ -42,6 +42,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import static org.openapitools.codegen.CodegenConstants.*;
import static org.openapitools.codegen.languages.KotlinClientCodegen.*;
@@ -1505,4 +1506,21 @@ public void testNoDefaultImplWhenNeitherSourceIsSet() throws IOException {
Assert.assertTrue(sawJsonTypeInfo,
"Expected at least one generated model with @JsonTypeInfo to exercise the code path");
}
+
+ /**
+ * AbstractKotlinCodegen calls cliOptions.clear(), so an option inherited from DefaultCodegen stays
+ * functional while vanishing from config-help and docs/generators/kotlin.md. That is how
+ * enumUnknownDefaultCase went undocumented for years; this guards the re-registration.
+ */
+ @Test
+ public void testEnumUnknownDefaultCaseIsRegisteredAsCliOption() {
+ CliOption option = new KotlinClientCodegen().cliOptions().stream()
+ .filter(o -> CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE.equals(o.getOpt()))
+ .findFirst()
+ .orElse(null);
+
+ Assert.assertNotNull(option, CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE + " is not registered");
+ Assert.assertEquals(option.getDefault(), "false");
+ Assert.assertEquals(option.getEnum().keySet(), Set.of("true", "false"));
+ }
}