apple/pkl · error · KotlinCodeGeneratorException
Cannot generate Kotlin enum class for Pkl type alias
Error message
Cannot generate Kotlin enum class for Pkl type alias `${typeAlias.displayName}` because string literal type "$literal" cannot be converted to a valid enum constant name. What it means
When generating a Kotlin enum class for a Pkl string-literal type alias, each literal must map to a valid Kotlin enum constant name via CodeGeneratorUtils.toEnumConstantName. A literal that cannot be converted (e.g. empty or entirely invalid characters) causes this KotlinCodeGeneratorException in generateEnumTypeSpec.
Solutions
- Remove or rename the offending literal in the Pkl type alias so it maps to a valid identifier.
- Replace the string-literal alias with a class property typed String if arbitrary values are allowed.
- Adjust the literal to start with a letter/underscore and contain identifier-safe characters.
Example fix
// before (Pkl) typealias Mode = "" | "fast" // after typealias Mode = "default" | "fast"
Defensive patterns
Strategy: validation
Validate before calling
// Validate each literal maps to a valid identifier before codegen fun validKotlinConst(literal: String) = literal.isNotEmpty() && CodeGeneratorUtils.toEnumConstantName(literal) != null
Type guard
fun isEnumCodegenSafe(alias: PType.Alias): Boolean =
alias.stringLiterals().all { CodeGeneratorUtils.toEnumConstantName(it) != null } Try / catch
try {
generator.generate(module)
} catch (e: KotlinCodeGeneratorException) {
if (e.message?.contains("cannot be converted to a valid enum constant name") == true) {
logger.error("Fix or drop the offending literal: ${e.message}")
} else throw e
} Prevention
- Avoid empty or punctuation-only string literals in enum-like typealiases
- Ensure at least one identifier-safe character (letter/underscore) per literal
- Add a schema lint that runs toEnumConstantName over all literal aliases
When it happens
Trigger: A type alias like `typealias X = ""|"a"` or literals consisting only of characters that cannot form an identifier, processed while generating an enum from stringLiterals.
Common situations: Pkl aliases containing empty string literals, whitespace-only strings, or strings of punctuation/emoji being code-generated to Kotlin.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Cannot generate Kotlin enum class for Pkl type alias
- Cannot generate Java enum class for Pkl type alias
- Cannot generate Java enum class for Pkl type alias
- Cannot generate Kotlin code for a Pkl standard library…
- I/O error writing file `$outputFile`. Cause
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/d13ce5120946d5d7.
Report an issue: GitHub.
Appendix: source
Thrown at pkl-codegen-kotlin/src/main/kotlin/org/pkl/codegen/kotlin/KotlinCodeGenerator.kt:551
builder.addFunction(generateEqualsMethod()).addFunction(generateHashCodeMethod())
}
return builder
}
return if (superclass == null && !pClass.isAbstract && !pClass.isOpen) generateDataClass()
else generateRegularClass()
}
private fun generateEnumTypeSpec(
typeAlias: TypeAlias,
stringLiterals: Set<String>,
): TypeSpec.Builder {
val enumConstantToPklNames =
stringLiterals
.groupingBy { literal ->
CodeGeneratorUtils.toEnumConstantName(literal)
?: throw KotlinCodeGeneratorException(
"Cannot generate Kotlin 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 KotlinCodeGeneratorException(
"Cannot generate Kotlin 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)
.primaryConstructor(
FunSpec.constructorBuilder().addParameter("value", String::class).build()
)
.addProperty(PropertySpec.builder("value", String::class).initializer("value").build())View on GitHub (pinned to f3efcbfc9b)