Skip to content

Code model deserialization cannot resolve references first defined inside decorator arguments #11981

Description

Description

Reference-preserving code-model JSON can fail to deserialize when a shared object is first serialized inside a decorator argument and referenced later from the main code-model graph.

For example, the serialized shape can effectively contain:

{
  "decorators": [
    {
      "name": "example",
      "arguments": {
        "value": {
          "$id": "2463",
          "name": "SharedModel"
        }
      }
    }
  ],
  "models": [
    {
      "$ref": "2463"
    }
  ]
}

The C# code-model reader currently captures decorator arguments as opaque JSON/BinaryData. Because those nested values are not deserialized through the shared TypeSpec reference resolver, $id: 2463 is never registered. Deserialization later reaches $ref: 2463 in the ordinary model graph and fails with an error similar to:

System.Text.Json.JsonException: cannot resolve reference 2463

We encountered this while upgrading the Azure management-plane C# generator. The immediate SDK-side mitigation removes model-valued arguments from known decorators before serializing the code model, but this is fragile: new decorators can reintroduce the same graph shape, and consumers may legitimately need those arguments.

Suggested change

Decorator arguments should participate in the same reference-resolution pass as the rest of the code model. Possible approaches include:

  1. Deserialize decorator argument values through the shared TypeSpecReferenceResolver rather than capturing their raw JSON directly.
  2. Pre-scan the complete JSON document to register all $id nodes before resolving $ref nodes, including IDs nested under opaque or extensibility properties.
  3. Preserve raw decorator JSON only after reference metadata has been registered or normalized, so opaque payload handling cannot hide graph identities from the resolver.

The desired behavior is that a $ref remains resolvable regardless of where the corresponding $id first appears in the serialized document.

Impact

This failure blocked regeneration of multiple Azure management SDK libraries after a dependency upgrade. Sanitizing decorator arguments avoids the immediate exception but loses metadata and does not address the underlying deserializer behavior.

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 workingemitter:client:csharpIssue for the C# client emitter: @typespec/http-client-csharp

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions