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

  1. matt-edmondson commented on Sep 14, 2026

    @matt-edmondson
    ContributorAuthor

    Triage

    Category: Bug
    Priority: High
    Suggested assignment: none — no specific team/area indicated; owner is the toolkit's metadata/diagnostics area (MetadataFile.cs)
    Possible duplicate: none found — this is the only open issue in this repo
    Already in progress: no — no open PR in the org touches this

    Why High: it breaks the toolkit's own stated design guarantee (a malformed file always reports a diagnostic) and fails in the worst direction — an uncaught NotSupportedException escapes to the Roslyn driver as a generic CS8785, which tells the consuming repo nothing about which file or why. The blast radius is wider than one file: the throw aborts every other declared file in the same RegisterSourceOutput invocation. The triggering shapes (an interface-typed property, a record with two constructors) are ordinary modelling choices, not exotic input.

    Suggested next step: small, well-contained fix — broaden the catch to NotSupportedException (and likely InvalidOperationException, which System.Text.Json also raises for converter-configuration failures) and report MetadataParseFailed with the exception message, matching the existing JsonException branch. Worth a test asserting that sibling files in the same invocation still generate.


    Generated by Claude Code

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