{"record":{"id":"4ba9b33a67ed7614","repo":"apple/pkl","slug":"invalidhttpheaderreservedprefix","errorCode":"invalidHttpHeaderReservedPrefix","errorMessage":"HTTP header `{0}` starts with a reserved header prefix.","messagePattern":"HTTP header `(.+?)` starts with a reserved header prefix\\.","errorType":"error_code","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/util/IoUtils.java","lineNumber":938,"sourceCode":"  private static boolean hasReservedHeaderPrefix(String headerName) {\n    var normalizedHeader = headerName.toLowerCase(Locale.ROOT);\n    for (var prefix : reservedHeaderPrefixes) {\n      if (normalizedHeader.startsWith(prefix)) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  // keep in sync with stdlib EvaluatorSettings.HttpHeaderName\n  public static void validateHeaderName(String headerName) {\n    if (isReservedHeaderName(headerName)) {\n      throw new IllegalArgumentException(\n          ErrorMessages.create(\"invalidHttpHeaderReserved\", headerName));\n    }\n\n    if (hasReservedHeaderPrefix(headerName)) {\n      throw new IllegalArgumentException(\n          ErrorMessages.create(\"invalidHttpHeaderReservedPrefix\", headerName));\n    }\n\n    if (!headerNameLike.matcher(headerName).matches()) {\n      throw new IllegalArgumentException(ErrorMessages.create(\"invalidHttpHeaderName\", headerName));\n    }\n  }\n\n  public static void validateHeaderValue(String headerValue) {\n    if (!headerValueLike.matcher(headerValue).matches()) {\n      throw new IllegalArgumentException(\n          ErrorMessages.create(\"invalidHttpHeaderValue\", headerValue));\n    }\n    if (headerValue.length() > 4096) {\n      throw new IllegalArgumentException(\n          ErrorMessages.create(\"invalidHttpHeaderValueTooLong\", headerValue));\n    }\n  }","sourceCodeStart":920,"sourceCodeEnd":956,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/util/IoUtils.java#L920-L956","documentation":"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().","triggerScenarios":"Passing a header name to validateHeaderName / evaluator external HTTP header config that starts with a reserved prefix, e.g. externalHttpHeaders[\"X-Pkl-Proxy\"] = \"...\".","commonSituations":"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.","solutions":["Rename the header to avoid the reserved prefix.","Drop the header entirely if Pkl already emits it automatically.","Consult the reserved-prefix list in IoUtils / EvaluatorSettings.HttpHeaderName to find a non-conflicting name."],"exampleFix":"// before\nexternalHttpHeaders {\n  [\"X-Pkl-Trace\"] = \"on\"\n}\n// after\nexternalHttpHeaders {\n  [\"X-My-Trace\"] = \"on\"\n}","handlingStrategy":"validation","validationCode":"if (name.startsWith(\"X-Pkl\") || hasReservedPrefix(name)) throw new IllegalArgumentException(\"reserved prefix: \" + name);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Review IoUtils' reserved prefixes before choosing header names.","Use your own vendor prefix for custom headers.","Reject reserved-prefix names at config ingestion time."],"tags":["http","validation","pkl"],"backgroundTag":"invalid-config-value","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}