{"record":{"id":"fd26291b4d30b674","repo":"apple/pkl","slug":"unexpected-blank-class-module-uri","errorCode":null,"errorMessage":"Unexpected blank class module URI","messagePattern":"Unexpected blank class module URI","errorType":"exception","errorClass":"DecodeException","httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/util/pklbinary/AbstractPklBinaryDecoder.java","lineNumber":339,"sourceCode":"    assertLength(PklBinaryCode.REGEX, len, 1);\n    currPath.push(\"'regex\");\n    var result = doDecodeRegex(Pattern.compile(unpacker.unpackString()));\n    unpacker.skipValue(len - 2);\n    currPath.pop();\n    return result;\n  }\n\n  private Object decodeClass(int len) throws IOException {\n    assertLength(PklBinaryCode.CLASS, len, 2);\n    currPath.push(\"'class\");\n\n    var name = unpacker.unpackString();\n    if (name.isBlank()) {\n      throw new DecodeException(\"Unexpected blank class name\");\n    }\n    var moduleUriString = unpacker.unpackString();\n    if (moduleUriString.isBlank()) {\n      throw new DecodeException(\"Unexpected blank class module URI\");\n    }\n    var moduleUri = URI.create(moduleUriString);\n\n    var result = doDecodeClass(name, moduleUri);\n    unpacker.skipValue(len - 3);\n    currPath.pop();\n    return result;\n  }\n\n  private Object decodeTypeAlias(int len) throws IOException {\n    assertLength(PklBinaryCode.TYPEALIAS, len, 2);\n    currPath.push(\"'typealias\");\n\n    var name = unpacker.unpackString();\n    if (name.isBlank()) {\n      throw new DecodeException(\"Unexpected blank typealias name\");\n    }\n    var moduleUriString = unpacker.unpackString();","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/util/pklbinary/AbstractPklBinaryDecoder.java#L321-L357","documentation":"Thrown by decodeClass when the CLASS entry's module URI string is blank. The decoder resolves the class via (name, moduleUri); without a valid module URI the reference cannot be resolved, so the payload is rejected as malformed.","triggerScenarios":"Decoding pkl-binary bytes where the second string of a CLASS entry is empty; an encoder omitting the module URI; corruption causing a mis-split of the string fields.","commonSituations":"Third-party encoders missing the URI field; files truncated mid-entry; decoder expecting a newer CLASS layout than the encoder produced.","solutions":["Ensure the encoder writes the module URI (e.g. file:///... or pkl:base#Module) after the name","Regenerate the payload with a matching Pkl version","Validate the payload's integrity (check lengths/hashes) before decoding","Reject blank module URIs at the producer"],"exampleFix":"// before\npacker.packString(name);\n// after\npacker.packString(name);\npacker.packString(module.getUri().toString());","handlingStrategy":"validation","validationCode":"if (moduleUri == null || moduleUri.isBlank()) throw new IllegalArgumentException(\"blank class module URI\");","typeGuard":null,"tryCatchPattern":"try {\n  return decoder.decode(bytes);\n} catch (DecodeException e) {\n  if (e.getMessage().contains(\"blank class module URI\")) {\n    throw new MalformedPklBinaryException(e);\n  }\n  throw e;\n}","preventionTips":["Always write the module URI as the second string of a CLASS entry","Take URIs from the module metadata, not hand-typed strings","Keep producer/consumer versions aligned","Checksum payloads"],"tags":["pkl","binary-decoder","corrupt-payload"],"backgroundTag":"empty-required-field","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}