apple/pkl · error · VmException

e.getMessage()

Error message

e.getMessage()

What it means

Thrown by the Bytes variant of fromBase64 (String.toBytes via Base64 decoding) when the input is not valid Base64. Identical decoder rules as the text variant: illegal characters, bad padding, or invalid length cause the decoder's IllegalArgumentException to be raised as an eval error.

Solutions

  1. Validate Base64 syntax (padding, alphabet, length % 4) before decoding
  2. Translate URL-safe '-'/'_' to '+/' when the source is base64url
  3. Strip whitespace/newlines that may have been inserted by wrapping
  4. Check the source encoding of the blob — it may not be Base64 at all

Example fix

// before
val bytes = blob.toBytes()
// after
val bytes = blob.replace("-", "+").replace("_", "/").toBytes()
Defensive patterns

Strategy: validation

Validate before calling

function isStandardBase64(s: String): Boolean = s.replaceAll("\n", "").isRegexMatch(/^[A-Za-z0-9+/]*={0,2}$/, _) && s.replaceAll("\n", "").length % 4 == 0

Prevention

When it happens

Trigger: Calling the bytes-returning Base64 decoder on a malformed string: wrong padding ("YWJ"), non-Base64 characters, or URL-safe alphabet without conversion.

Common situations: Decoding binary blobs from HTTP responses or files that were truncated; mixing base64 and base64url encodings; copying values that lost trailing '=' padding.

Related errors


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

Appendix: source

Thrown at pkl-core/src/main/java/org/pkl/core/stdlib/base/StringNodes.java:1022

        return new String(Base64.getDecoder().decode(self), StandardCharsets.UTF_8);
      } catch (IllegalArgumentException e) {
        throw exceptionBuilder()
            .adhocEvalError(e.getMessage())
            .withProgramValue("String", self)
            .withCause(e)
            .build();
      }
    }
  }

  public abstract static class base64DecodedBytes extends ExternalPropertyNode {
    @TruffleBoundary
    @Specialization
    protected VmBytes eval(String self) {
      try {
        return new VmBytes(Base64.getDecoder().decode(self));
      } catch (IllegalArgumentException e) {
        throw exceptionBuilder()
            .adhocEvalError(e.getMessage())
            .withProgramValue("String", self)
            .withCause(e)
            .build();
      }
    }
  }

  public abstract static class encodeToBytes extends ExternalMethod1Node {
    @TruffleBoundary
    @Specialization
    protected VmBytes eval(String self, String charsetName) {
      try {
        var bytes = self.getBytes(charsetName);
        return new VmBytes(bytes);
      } catch (UnsupportedEncodingException e) {
        throw PklBugException.unreachableCode();
      }

View on GitHub (pinned to f3efcbfc9b)