Skip to content

MetadataFile.Deserialize crashes the generator on unsupported types instead of reporting the documented diagnostic #5

Description

@matt-edmondson

What happens

MetadataFile.Deserialize<T> (SourceGeneratorToolkit/MetadataFile.cs, lines 109-128) wraps JsonSerializer.Deserialize<T>(Text, DeserializeOptions) in a try that only catches System.Text.Json.JsonException (line 123). Per System.Text.Json's documented behavior, deserializing into a type with no compatible converter throws System.NotSupportedException, which is a distinct, sibling exception type — not caught here.

Confirmed by direct execution:

  • An interface- or abstract-typed metadata model throws NotSupportedException: Deserialization of interface or abstract types is not supported. Type 'IThing'.
  • A metadata model with two ambiguous public constructors and no [JsonConstructor] throws NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported.

Why it matters

This directly undermines the toolkit's own stated design guarantee (per CLAUDE.md): "A missing or malformed file always reports... swallowing an exception means malformed metadata silently generates something wrong / produces no diagnostic."

Concretely: a consuming repository models a metadata DTO with an interface-typed property (a natural choice for e.g. "one of several variant kinds"), or a record with two constructors and no [JsonConstructor]. As soon as any AdditionalFile has that shape, Deserialize<T> throws NotSupportedException, which propagates out of GeneratorBase<T>.Generate and out of the RegisterSourceOutput callback uncaught. The Roslyn driver catches this at its own top level and reports the generic CS8785 ("Generator failed to generate source... Exception was of type 'NotSupportedException'") instead of the toolkit's intended MetadataParseFailed diagnostic. For a multi-file generator, this also aborts processing of every other file in the same RegisterSourceOutput invocation, not just the offending one.

Suggested fix

Broaden the catch in Deserialize<T> to also catch NotSupportedException (and consider InvalidOperationException, which System.Text.Json also uses for some converter-configuration failures), reporting parseFailed with the exception's message the same way the existing JsonException branch does — so any deserialization failure degrades to the documented diagnostic instead of crashing the generator.

Acceptance criteria

  • An AdditionalFile that deserializes to an interface/abstract type, or to a type with ambiguous constructors, produces the toolkit's MetadataParseFailed-style diagnostic instead of a generator crash / CS8785.
  • Other declared files in the same generator invocation still process normally when one file fails to deserialize this way.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions