OrchardCMS/OrchardCore · error · NotSupportedException

Deserializing a is not supported.

Error message

Deserializing a {typeof(T).Name} is not supported.

What it means

JsonDynamicJsonConverter<T> intentionally throws NotSupportedException in Read because JsonDynamicBase-derived types (dynamic JSON wrappers) can only be written (serialized), never deserialized back into the typed wrapper. The converter is write-only by design: the underlying JsonNode-based value cannot be reconstructed into the original dynamic subclass. Hitting this means your code asked System.Text.Json to round-trip a type that only supports the write direction.

Solutions

  1. Deserialize into JsonNode / JsonDocument / a plain DTO instead of the JsonDynamicBase-derived type.
  2. Wrap deserialization in your own two-step approach: parse to JsonNode, then construct the dynamic wrapper manually if a constructor exists.
  3. Remove the dynamic type from deserialization paths — keep it only for serialization; define a separate read model.
  4. Audit options.Converters registrations and remove JsonDynamicJsonConverter<T> from generic global registration if it causes unintended routing.
  5. If round-tripping is required, write your own JsonConverter<T> that parses to JsonNode and instantiates the concrete dynamic type.

Example fix

// before
var doc = JsonSerializer.Deserialize<MyJsonDynamicObject>(json, options); // throws

// after
var node = JsonNode.Parse(json);
var doc = new MyJsonDynamicObject(node); // construct manually from the parsed node
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof(JsonDynamicBase).IsAssignableFrom(targetType))
    throw new InvalidOperationException($"{targetType.Name} is serialize-only; deserialize into JsonNode or a DTO instead.");

Type guard

static bool IsDeserializable<T>() => !typeof(JsonDynamicBase).IsAssignableFrom(typeof(T));
// guard at call site:
// if (IsDeserializable<MyJsonDynamicObject>()) var x = JsonSerializer.Deserialize<MyJsonDynamicObject>(json);

Try / catch

try
{
    return JsonSerializer.Deserialize<T>(json, options);
}
catch (NotSupportedException ex) when (ex.Message.Contains("is not supported"))
{
    var node = JsonNode.Parse(json);
    return node is null ? null : new T(node); // construct from parsed node via your factory
}

Prevention

When it happens

Trigger: Calling JsonSerializer.Deserialize<T> (or Deserialize anonymously via an API model) where T is a JsonDynamicBase-derived type registered with JsonDynamicJsonConverter<T> — e.g. deserializing a stored payload back into a JsonDynamicObject/JsonDynamicValue type.

Common situations: Persisting a dynamic JSON document and later trying to load it back into the same dynamic wrapper type; using the dynamic type in an API controller's [FromBody] or a deserialization-heavy path; wiring the converter globally via options.Converters.Add so accidental Deserialize calls route to it.

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 OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/3fbfb09450e1f7b0. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore/OrchardCore.Abstractions/Json/Serialization/JsonDynamicJsonConverter.cs:11

using System.Text.Json.Dynamic;

#nullable enable

namespace System.Text.Json.Serialization;

public sealed class JsonDynamicJsonConverter<T> : JsonConverter<T> where T : JsonDynamicBase
{
    public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotSupportedException($"Deserializing a {typeof(T).Name} is not supported.");
    }

    public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
    {
        if (value.Node != null)
        {
            value.Node.WriteTo(writer, options);
        }
        else
        {
            writer.WriteNullValue();
        }
    }
}

View on GitHub (pinned to 4306c0717f)