apple/pkl · error · DecodeException
unhandledMessageCode
unhandledMessageCode
Error message
unhandledMessageCode
What it means
decodeMessage returned null for a recognized message type, meaning the concrete decoder subclass does not implement handling for that message code. The decoder treats this as a protocol gap and throws unhandledMessageCode with the hex code.
Source
Thrown at pkl-core/src/main/java/org/pkl/core/messaging/AbstractMessagePackDecoder.java:82
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(
ErrorMessages.create("unhandledMessageCode", Integer.toHexString(code)));
} catch (MessageTypeException | URISyntaxException e) {
throw new DecodeException(ErrorMessages.create("malformedMessageBody", code), e);
}
}
protected static @Nullable Value getNullable(Map<Value, Value> map, String key) {
return map.get(new ImmutableStringValueImpl(key));
}
protected static Value get(Map<Value, Value> map, String key) throws DecodeException {
var value = map.get(new ImmutableStringValueImpl(key));
if (value == null) {
throw new DecodeException(ErrorMessages.create("missingMessageParameter", key));
}
return value;
}
View on GitHub (pinned to f3efcbfc9b)
Solutions
- Implement a decodeMessage branch for the reported message type
- Override decodeMessage to skip (return a no-op message) instead of null for ignorable types
- Filter the stream upstream to drop unhandled message codes
- Update to a decoder version that covers all message types
Example fix
// before case CAN_EVALUATE -> null; // falls through to unhandledMessageCode // after case CAN_EVALUATE -> decodeCanEvaluate(map); // implement or explicitly skip
Defensive patterns
Strategy: fallback
Try / catch
try { return decoder.decode(unpacker); } catch (DecodeException e) { if (String.valueOf(e.getMessage()).contains("unhandledMessageCode")) { return MessageSkip.INSTANCE; /* or rethrow */ } throw e; } Prevention
- Implement all message types in decodeMessage
- Return explicit skip messages instead of null
- Cover new message types when upgrading
When it happens
Trigger: A Type is recognized by Type.fromInt but decodeMessage(msgType, map) has no case for it and returns null.
Common situations: Custom or partial decoder implementations missing handlers for some message types (e.g. LogMessage, WarningMessage); base-class users decoding streams that include control messages they didn't implement.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- malformedMessageHeaderLength
- malformedMessageHeaderException
- malformedMessageHeaderUnrecognizedCode
- malformedMessageBody
- missingMessageParameter
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/4aadd53c3131cd5a.
Report an issue: GitHub.