Skip to content

A metadata model whose constructor throws (e.g. a null guard) crashes the generator with CS8785 and drops every other file's output #25

Description

@matt-edmondson

What's wrong

MetadataFile.Deserialize<T> (SourceGeneratorToolkit/MetadataFile.cs:119-148) catches only JsonException, NotSupportedException and InvalidOperationException. System.Text.Json does not wrap exceptions thrown by the model's own constructor. A model with an ordinary guard clause therefore throws straight through to the Roslyn driver when a property is missing from the JSON. That is exactly the outcome the method's remarks, and CLAUDE.md, say the catch exists to prevent: a generic CS8785 that names neither the file nor the reason, with every other file in the invocation abandoned.

Repro

public record GuardedThing
{
    public GuardedThing(string name) => Name = name ?? throw new ArgumentNullException(nameof(name));
    public string Name { get; }
}
public class ThingsModel { public List<GuardedThing> Things { get; set; } = []; }

Use a two-file generator shaped like the test project's ResilientPairGenerator (things.json + others.json). Supply things.json = {"things":[{"kind":"x"}]} (the name is missing) and a valid others.json.

  • Observed: result.Exception is ArgumentNullException, with warning CS8785: Generator '…' failed to generate source. It emits 0 sources, so the valid others.json output is lost too.
  • Expected: a parse-failed diagnostic naming things.json, with others.json still generated. A bad Version value is already handled this way (control case).

Suggested fix

Add catch (ArgumentException ex) { return ParseFailed(ex); }, which also covers ArgumentNullException and ArgumentOutOfRangeException. The stated aim is that nothing escapes to the driver, so a stronger option is a catch-all with a filter that excludes OperationCanceledException. Add a guarded-constructor fixture next to AmbiguousMetadata so this path stays covered.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    readyFully specified; implement as written

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions