apple/pkl · error · RuntimeException

Unexpected runtimeData line: $line

Error message

Unexpected runtimeData line: $line

What it means

DocMigrator.parseLegacyRuntimeData reads each line of a legacy runtime-data file and matches it against known prefixes (e.g. LEGACY_KNOWN_SUBTYPES_PREFIX). A line that matches no known prefix means the legacy file is corrupt, truncated, or from an unrecognized format, so parsing fails with this RuntimeException.

Solutions

  1. Restore the runtime-data file from version control or regenerate the docsite
  2. Compare the offending line against the expected legacy line prefixes
  3. Delete the legacy file(s) and regenerate documentation from source
Defensive patterns

Strategy: try-catch

Try / catch

try { docMigrator.migrate() } catch (e: RuntimeException) { if (e.message?.startsWith("Unexpected runtimeData line") == true) { restoreOrRegenerateRuntimeData() } else throw e }

Prevention

When it happens

Trigger: Calling DocMigrator (which parses legacy runtime data) on a runtime-data file containing a line that is not blank and does not start with any recognized legacy prefix.

Common situations: Hand-edited or corrupted runtime-data file; docsite produced by a much older or newer pkl-doc whose line format differs; partial file write leaving malformed lines.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/947549bbc7a2cf16. Report an issue: GitHub.

Appendix: source

Thrown at pkl-doc/src/main/kotlin/org/pkl/doc/DocMigrator.kt:94

                  ) { link ->
                    // fill in missing href
                    if (link.href != null) link else link.copy(href = myVersionHref)
                  }
                runtimeData.copy(knownVersions = knownVersions)
              }

              line.startsWith(LEGACY_KNOWN_USAGES_PREFIX) -> {
                val knownUsages = readLegacyLine(line, LEGACY_KNOWN_USAGES_PREFIX, LEGACY_SUFFIX)
                runtimeData.copy(knownUsages = knownUsages)
              }

              line.startsWith(LEGACY_KNOWN_SUBTYPES_PREFIX) -> {
                val knownSubtypes =
                  readLegacyLine(line, LEGACY_KNOWN_SUBTYPES_PREFIX, LEGACY_SUFFIX)
                runtimeData.copy(knownSubtypes = knownSubtypes)
              }

              else -> throw RuntimeException("Unexpected runtimeData line: $line")
            }
        }
        return runtimeData
      } catch (e: NoSuchFileException) {
        throw e
      }
    }

    private fun readLegacyLine(line: String, prefix: String, suffix: String): Set<RuntimeDataLink> {
      val jsStr = line.substring(prefix.length, line.length - suffix.length)
      return json.decodeFromString<List<RuntimeDataLink>>(jsStr).toSet()
    }
  }

  val isUpToDate by lazy {
    if (!Files.exists(outputDir.resolve("index.html"))) {
      // must be the first run
      return@lazy true

View on GitHub (pinned to f3efcbfc9b)