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
- Deserialize into JsonNode / JsonDocument / a plain DTO instead of the JsonDynamicBase-derived type.
- Wrap deserialization in your own two-step approach: parse to JsonNode, then construct the dynamic wrapper manually if a constructor exists.
- Remove the dynamic type from deserialization paths — keep it only for serialization; define a separate read model.
- Audit options.Converters registrations and remove JsonDynamicJsonConverter<T> from generic global registration if it causes unintended routing.
- 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
- Treat all JsonDynamicBase-derived types as write-only in your data flow.
- Maintain separate read models (DTOs or JsonNode) for deserialization paths.
- Never register JsonDynamicJsonConverter<T> as a global catch-all converter.
- Search the codebase for Deserialize<> calls on dynamic wrapper types during reviews.
- Document the one-way nature of these types near their definitions.
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
- Unknown token type
- Unexpected token type
- Unexpected token parsing TimeSpan. Expected a string, got
- Unable to convert ' ' to TimeSpan.
- Cannot convert to
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)