apple/pkl · error · IllegalArgumentException

invalidHttpHeaderReservedPrefix

invalidHttpHeaderReservedPrefix

Error message

HTTP header `{0}` starts with a reserved header prefix.

What it means

Pkl rejects HTTP header names that begin with a reserved prefix (e.g. headers like X-Pkl-... or other managed prefixes) to prevent users from injecting headers the HTTP client treats specially. Thrown from IoUtils.validateHeaderName via hasReservedHeaderPrefix().

Source

Thrown at pkl-core/src/main/java/org/pkl/core/util/IoUtils.java:938

  private static boolean hasReservedHeaderPrefix(String headerName) {
    var normalizedHeader = headerName.toLowerCase(Locale.ROOT);
    for (var prefix : reservedHeaderPrefixes) {
      if (normalizedHeader.startsWith(prefix)) {
        return true;
      }
    }
    return false;
  }

  // keep in sync with stdlib EvaluatorSettings.HttpHeaderName
  public static void validateHeaderName(String headerName) {
    if (isReservedHeaderName(headerName)) {
      throw new IllegalArgumentException(
          ErrorMessages.create("invalidHttpHeaderReserved", headerName));
    }

    if (hasReservedHeaderPrefix(headerName)) {
      throw new IllegalArgumentException(
          ErrorMessages.create("invalidHttpHeaderReservedPrefix", headerName));
    }

    if (!headerNameLike.matcher(headerName).matches()) {
      throw new IllegalArgumentException(ErrorMessages.create("invalidHttpHeaderName", headerName));
    }
  }

  public static void validateHeaderValue(String headerValue) {
    if (!headerValueLike.matcher(headerValue).matches()) {
      throw new IllegalArgumentException(
          ErrorMessages.create("invalidHttpHeaderValue", headerValue));
    }
    if (headerValue.length() > 4096) {
      throw new IllegalArgumentException(
          ErrorMessages.create("invalidHttpHeaderValueTooLong", headerValue));
    }
  }

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Rename the header to avoid the reserved prefix.
  2. Drop the header entirely if Pkl already emits it automatically.
  3. Consult the reserved-prefix list in IoUtils / EvaluatorSettings.HttpHeaderName to find a non-conflicting name.

Example fix

// before
externalHttpHeaders {
  ["X-Pkl-Trace"] = "on"
}
// after
externalHttpHeaders {
  ["X-My-Trace"] = "on"
}
Defensive patterns

Strategy: validation

Validate before calling

if (name.startsWith("X-Pkl") || hasReservedPrefix(name)) throw new IllegalArgumentException("reserved prefix: " + name);

Prevention

When it happens

Trigger: Passing a header name to validateHeaderName / evaluator external HTTP header config that starts with a reserved prefix, e.g. externalHttpHeaders["X-Pkl-Proxy"] = "...".

Common situations: Users copying vendor-specific headers from curl commands that collide with Pkl's reserved prefixes; middleware configs where a proxy expects these headers to be set client-side.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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