stride3d/stride · error · NotSupportedException

Legacy (pre-4.2) ServiceWire complex-type deserialize is…

Error message

Legacy (pre-4.2) ServiceWire complex-type deserialize is not supported.

What it means

The non-generic LegacyServiceWire.Deserialize(bytes, typeConfigName) path never had legacy support: complex-typed deserialization over the pre-4.2 wire protocol is not implemented, so the adapter always throws NotSupportedException. Only ServiceSyncInfo via the generic Deserialize<T> is supported.

Solutions

  1. Use the generic Deserialize<ServiceSyncInfo>(bytes) for legacy sync-info payloads.
  2. Route complex-type deserialization through the modern ServiceWire serializer (post-4.2) rather than the legacy adapter.
  3. If a payload arrives over legacy transport but is a complex type, upgrade both ends to the current protocol.

Example fix

// before
var obj = (MyMessage)legacyWire.Deserialize(bytes, "MyMessage"); // always throws
// after
var info = legacyWire.Deserialize<ServiceSyncInfo>(bytes); // supported legacy path
Defensive patterns

Strategy: try-catch

Validate before calling

// avoid the non-generic legacy overload entirely; if you must call it, treat it as unsupported:
bool legacyComplexTypesSupported = false;

Try / catch

try { obj = legacyWire.Deserialize(bytes, typeConfigName); }
catch (NotSupportedException) { obj = modernWire.Deserialize(bytes, typeConfigName); }

Prevention

When it happens

Trigger: Calling Deserialize(bytes, typeConfigName) — the non-generic, type-name-based overload — on LegacyServiceWire with any payload.

Common situations: Generic IPC infrastructure resolving types by config name at runtime and routing through the legacy adapter; refactored serializers calling the non-generic interface member.

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


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/dbaf1858a255c7d2. Report an issue: GitHub.

Appendix: source

Thrown at sources/launcher/Stride.Cli/Legacy/LegacyServiceWire.cs:31

// ServiceWire (4.2+) switched to a JSON serializer, which the stock client already speaks.
//
// BinaryFormatter is gone from modern .NET, so we can't round-trip that payload with the stock serializer.
// It's the only serializer call on the client's GenerateShaderKeys path, though: the method's string arguments
// and byte[] result travel as ServiceWire primitive type-codes, never through the serializer. So we only need
// to read that one payload, which we do with the safe NRBF reader and rebuild ServiceSyncInfo by hand.
internal sealed class LegacyBinaryFormatterSerializer : ISerializer
{
    public T Deserialize<T>(byte[] bytes)
    {
        if (bytes is null || bytes.Length == 0)
            return default!;
        if (typeof(T) == typeof(ServiceSyncInfo))
            return (T)(object)ReadServiceSyncInfo(bytes);
        throw new NotSupportedException($"Legacy (pre-4.2) ServiceWire deserialize of {typeof(T)} is not supported.");
    }

    public object Deserialize(byte[] bytes, string typeConfigName)
        => throw new NotSupportedException("Legacy (pre-4.2) ServiceWire complex-type deserialize is not supported.");

    public byte[] Serialize<T>(T obj)
        => throw new NotSupportedException("Legacy (pre-4.2) ServiceWire complex-type serialize is not supported.");

    public byte[] Serialize(object obj, string typeConfigName)
        => throw new NotSupportedException("Legacy (pre-4.2) ServiceWire complex-type serialize is not supported.");

    private static ServiceSyncInfo ReadServiceSyncInfo(byte[] bytes)
    {
        var root = (ClassRecord)NrbfDecoder.Decode(new MemoryStream(bytes));

        var methodRecords = ((SZArrayRecord<SerializationRecord>)root.GetArrayRecord(Member(root, "MethodInfos"))).GetArray();
        var methods = new MethodSyncInfo[methodRecords.Length];
        for (var i = 0; i < methodRecords.Length; i++)
        {
            var method = (ClassRecord)methodRecords[i]!;
            methods[i] = new MethodSyncInfo
            {

View on GitHub (pinned to 96fad776d2)