{"record":{"id":"94b47bd522963f98","repo":"dotnet/aspnetcore","slug":"extension-types-are-not-supported","errorCode":null,"errorMessage":"Extension types are not supported","messagePattern":"Extension types are not supported","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/SignalR/clients/java/signalr/messagepack/src/main/java/com/microsoft/signalr/messagepack/MessagePackHubProtocol.java","lineNumber":633,"sourceCode":"                    if (itemType == null) {\n                        return null;\n                    }\n                    return objectMapper.readValue(payloadBytes, payload.position() + (int) readBytesStart, (int) (unpacker.getTotalReadBytes() - readBytesStart),\n                            typeFactory.constructType(itemType));\n                } else {\n                    // This is an inner call to readValue - we just need to read the right number of bytes\n                    // We can return null, and the outermost call will know how many bytes to give to objectMapper.\n                    return null;\n                }\n            case EXTENSION:\n                /*\n                ExtensionTypeHeader extension = unpacker.unpackExtensionTypeHeader();\n                byte[] extensionValue = new byte[extension.getLength()];\n                unpacker.readPayload(extensionValue);\n                //Convert this to an object?\n                item = extensionValue;\n                */\n                throw new RuntimeException(\"Extension types are not supported\");\n            default:\n                return null;\n        }\n        // If itemType was null, we were just in this method to advance the buffer. return null.\n        if (itemType == null) {\n            return null;\n        }\n        // If we get here, the item isn't a map or a collection/array, so we use the Class to cast it\n        if (itemClass.isPrimitive()) {\n            return Utils.toPrimitive(itemClass, item);\n        }\n        return itemClass.cast(item);\n    }\n\n    private void writeValue(Object o, MessagePacker packer) throws IOException {\n        packer.addPayload(objectMapper.writeValueAsBytes(o));\n    }\n}","sourceCodeStart":615,"sourceCodeEnd":651,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/SignalR/clients/java/signalr/messagepack/src/main/java/com/microsoft/signalr/messagepack/MessagePackHubProtocol.java#L615-L651","documentation":"readValue switches on the msgpack ValueType of the next value; when it is EXTENSION the protocol deliberately throws because MessagePack extension types (custom application types, msgpack timestamps, etc.) have no deserializer wired up - the handling code is commented out at MessagePackHubProtocol.java:626-632.","triggerScenarios":"A value on the wire is encoded as a MessagePack extension type (the high-level format with a type tag). This happens when the server serializes a type that its MessagePack formatter emits as an ext, e.g. DateTime/timestamp via a custom formatter, or a type using MessagePack-CSharp's ext-code paths.","commonSituations":"Server uses a custom IMessagePackFormatter that writes ext-format bytes; .NET DateTime serialized with a timestamp ext; interop with a non-standard MessagePack producer.","solutions":["On the server, format the offending value as a primitive/string/POJO instead of a MessagePack extension type.","Convert timestamps to ISO-8601 strings or epoch longs before sending.","Register a client-side equivalent formatter only if you fork the protocol to re-enable the commented-out ext path."],"exampleFix":"// before (.NET) - formatter writes an ext type\noptions.FormatterResolvers = new[] { StandardResolverWithDateTime.KindDetection };\n// after - send DateTime as an ISO string\nhubContext.Clients.All.SendAsync(\"M\", myDate.ToString(\"O\"));","handlingStrategy":"type-guard","validationCode":"// On the server side, ensure values are not encoded as MessagePack ext by converting\n// e.g. DateTime -> ISO-8601 string before sending.\nstring payload = dateTime.ToString(\"O\", CultureInfo.InvariantCulture);","typeGuard":"// The Java client cannot guard ext types on the wire; guard at the source by not producing them.\n// Avoid registering formatters that emit ext format codes.","tryCatchPattern":"try {\n    List<HubMessage> msgs = protocol.parseMessages(buffer, binder);\n} catch (RuntimeException ex) {\n    if (\"Extension types are not supported\".equals(ex.getMessage())) {\n        // server is sending an ext-encoded value; fix server-side serialization\n        log.error(\"Server sent an unsupported msgpack extension type\", ex);\n    }\n    throw ex;\n}","preventionTips":["Do not use MessagePack extension formatters for values sent to the Java client.","Encode timestamps as ISO strings or epoch longs.","Keep to JSON-friendly POJOs over the wire."],"tags":["java","signalr","messagepack","deserialization","extension-type"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}