apple/pkl · error · JavaCodeGeneratorException
Cannot generate Java enum class for Pkl type alias
Error message
Cannot generate Java enum class for Pkl type alias `${typeAlias.displayName}` because string literal types "$firstLiteral" and "$secondLiteral" would both be converted to enum constant name `$enumConstantName`. What it means
During enum generation, distinct string literals that sanitize to the same Java enum constant name would collide (e.g. "foo-bar" and "foo_bar" both becoming FOO_BAR). The reduce step detects the collision and aborts, because two enum constants cannot share a name.
Solutions
- Rename one of the conflicting literals in the Pkl module so they produce distinct enum names.
- Normalize your value set to one convention (e.g. all kebab-case, no case-only differences).
- Check which literals collide by applying Java identifier sanitization rules manually.
- Fall back to String representation for the alias if the values cannot be changed.
Example fix
// before (Pkl) type Level = "log-level" | "log_level" // after type Level = "log-level" | "logLevel"
Defensive patterns
Strategy: validation
Validate before calling
val names = literals.map { CodeGeneratorUtils.toEnumConstantName(it) }; require(names.distinct().size == names.size) { "enum name collision: $literals" } Type guard
fun Set<String>.hasEnumCollisions() = groupingBy { CodeGeneratorUtils.toEnumConstantName(it)!! }.eachCount().any { it.value > 1 } Try / catch
try { generate() } catch (e: JavaCodeGeneratorException) { if ("would both be converted" in e.message!!) renameCollidingLiterals() else throw e } Prevention
- Keep string-literal unions in one naming convention
- Avoid values differing only by case or separators
- Deduplicate literals after sanitization in a pre-check
When it happens
Trigger: A string-literal type alias contains two literals that toEnumConstantName normalizes to the identical identifier — differing only in case, separators (-, ., spaces), or other characters stripped during sanitization.
Common situations: Modules mixing kebab-case and snake_case variants of the same word ("log-level" vs "log_level"), literals differing only in case, or values differing only by punctuation.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Cannot generate Java enum class for Pkl type alias
- Cannot generate Kotlin enum class for Pkl type alias
- Cannot generate Kotlin enum class for Pkl type alias
- Annotation `$fqn` is not a valid Java class. The name of…
- Cannot convert String
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/c1060b7b85b1cde7.
Report an issue: GitHub.
Appendix: source
Thrown at pkl-codegen-java/src/main/kotlin/org/pkl/codegen/java/JavaCodeGenerator.kt:665
.initializer("0L")
.build()
}
private fun generateEnumTypeSpec(
typeAlias: TypeAlias,
stringLiterals: Set<String>,
): TypeSpec.Builder {
val enumConstantToPklNames =
stringLiterals
.groupingBy { literal ->
CodeGeneratorUtils.toEnumConstantName(literal)
?: throw JavaCodeGeneratorException(
"Cannot generate Java enum class for Pkl type alias `${typeAlias.displayName}` " +
"because string literal type \"$literal\" cannot be converted to a valid enum constant name."
)
}
.reduce { enumConstantName, firstLiteral, secondLiteral ->
throw JavaCodeGeneratorException(
"Cannot generate Java enum class for Pkl type alias `${typeAlias.displayName}` " +
"because string literal types \"$firstLiteral\" and \"$secondLiteral\" " +
"would both be converted to enum constant name `$enumConstantName`."
)
}
val builder =
TypeSpec.enumBuilder(typeAlias.simpleName)
.addModifiers(Modifier.PUBLIC)
.addField(String::class.java, "value", Modifier.PRIVATE)
.addMethod(
MethodSpec.constructorBuilder()
.addModifiers(Modifier.PRIVATE)
.addParameter(String::class.java, "value")
.addStatement("this.value = value")
.build()
)
.addMethod(View on GitHub (pinned to f3efcbfc9b)