apple/pkl · error · DecodeException

Unexpected msgpack map value

Error message

Unexpected msgpack map value

What it means

DecodeException thrown by doDecode() when a top-level msgpack value has type MAP. Pkl's binary encoding represents all composite values as ARRAY headers whose first element is a PklBinaryCode; a bare msgpack map at top level is not valid, so decoding aborts.

Solutions

  1. Ensure the payload uses Pkl binary encoding (arrays tagged with PklBinaryCode), not plain msgpack maps
  2. Re-encode maps via Pkl's MAP-coded non-primitive structure
  3. Confirm you are decoding the correct stream/channel (Pkl binary output, not another msgpack feed)
  4. Check producer and consumer Pkl versions match
Defensive patterns

Strategy: validation

Validate before calling

// Producer side: maps must be Pkl MAP-coded arrays, not raw msgpack maps
packer.packArrayHeader(1 + entries);
packer.packInt(PklBinaryCode.MAP.toInt());
// then entries...

Try / catch

try {
  Object v = decoder.decode(bytes);
} catch (DecodeException e) {
  if ("Unexpected msgpack map value".equals(e.getMessage())) {
    // wrong serializer used upstream; re-encode with Pkl binary encoding
  } else throw e;
}

Prevention

When it happens

Trigger: Decoding output from a generic msgpack serializer that emitted a map at top level; hand-crafted msgpack; producer bug emitting map headers outside a non-primitive wrapper.

Common situations: Interoperability mistakes between msgpack tools and Pkl binary data; mixing evaluator message channels; corrupted framing where a map header appears where an array was expected.

Related errors


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

Appendix: source

Thrown at pkl-core/src/main/java/org/pkl/core/util/pklbinary/AbstractPklBinaryDecoder.java:151

    if (!unpacker.hasNext()) {
      throw new DecodeException("Unexpected EOF");
    }

    return switch (unpacker.getNextFormat().getValueType()) {
      // primitives
      case NIL -> {
        unpacker.unpackNil();
        yield doDecodeNull();
      }
      case STRING -> unpacker.unpackString();
      case INTEGER -> unpacker.unpackLong();
      case BOOLEAN -> unpacker.unpackBoolean();
      case FLOAT -> unpacker.unpackDouble();
      // non-primitive
      case ARRAY -> decodeNonPrimitive();
      // things we should never see outside a non-primitive
      case BINARY -> throw new DecodeException("Unexpected msgpack bin value");
      case MAP -> throw new DecodeException("Unexpected msgpack map value");
      case EXTENSION -> throw new DecodeException("Unexpected msgpack ext value");
    };
  }

  private Object decodeNonPrimitive() throws IOException {
    var len = unpacker.unpackArrayHeader();
    if (len < 1) {
      throw new DecodeException("Unexpected empty object array value");
    }

    var codeInt = unpacker.unpackInt();
    var code = PklBinaryCode.fromInt(codeInt);
    if (code == null) {
      throw new DecodeException("Unrecognized code 0x%x", (byte) codeInt);
    }

    return switch (code) {
      case OBJECT -> decodeObject(len);

View on GitHub (pinned to f3efcbfc9b)