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

  1. Remove or rename the offending literal in the Pkl type alias so it maps to a valid identifier.
  2. Replace the string-literal alias with a class property typed String if arbitrary values are allowed.
  3. 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

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


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)