apple/pkl · error · DecodeException

malformedMessageHeaderException

malformedMessageHeaderException

Error message

malformedMessageHeaderException

What it means

The first element of a message frame must be an integer message code. If unpackInt() hits a value of a different MessagePack type, a MessageTypeException is wrapped as DecodeException with code malformedMessageHeaderException.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/messaging/AbstractMessagePackDecoder.java:64

  protected abstract @Nullable Message decodeMessage(Type msgType, Map<Value, Value> map)
      throws DecodeException, URISyntaxException;

  @Override
  public @Nullable Message decode() throws IOException, DecodeException {
    if (!unpacker.hasNext()) {
      return null;
    }

    int code;
    try {
      var arraySize = unpacker.unpackArrayHeader();
      if (arraySize != 2) {
        throw new DecodeException(ErrorMessages.create("malformedMessageHeaderLength", arraySize));
      }
      code = unpacker.unpackInt();
    } catch (MessageTypeException e) {
      throw new DecodeException(ErrorMessages.create("malformedMessageHeaderException"), e);
    }

    Type msgType;
    try {
      msgType = Type.fromInt(code);
    } catch (IllegalArgumentException e) {
      throw new DecodeException(
          ErrorMessages.create("malformedMessageHeaderUnrecognizedCode", Integer.toHexString(code)),
          e);
    }

    try {
      var map = unpacker.unpackValue().asMapValue().map();
      var decoded = decodeMessage(msgType, map);
      if (decoded != null) {
        return decoded;
      }
      throw new DecodeException(

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Confirm the peer writes [int, map] frames with an integer first element
  2. Check you are reading from the binary channel, not a text/log stream
  3. Re-capture or regenerate the stream; inspect bytes at the failure offset
  4. Upgrade the peer library so both sides use the same message format

Example fix

// before: trusting the header code
var code = unpacker.unpackInt();
// after: guard against type errors upstream
if (!nextValueIsInteger(unpacker)) throw new IllegalStateException("expected integer message code, got " + describeNext(unpacker));
Defensive patterns

Strategy: validation

Validate before calling

// peek: first frame element must be an integer code
boolean headerIsInt = peekNextTypeIsInteger(unpacker);

Try / catch

try { return decoder.decode(unpacker); } catch (DecodeException e) { if (String.valueOf(e.getMessage()).contains("malformedMessageHeaderException")) { log.error("corrupt msgpack header at offset {}", bytesRead); } throw e; }

Prevention

When it happens

Trigger: Decoding a frame whose array element 0 is a string, nil, map, etc. instead of an integer code.

Common situations: Corrupted or hand-edited message files, wrong stream interleaving (e.g. reading stdout text into the msgpack channel), or peer encoding with an incompatible schema.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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