microsoft / microsoft/typespec
Code model deserialization cannot resolve references first defined inside decorator arguments
- Dominant language
- Java
- Stars
- 5.9k
- Forks
- 394
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 104
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:
```json
{
"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:
```text
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.
Contributor guide
Research direction
Start with the C# code-model reader and the shared TypeSpecReferenceResolver, then reproduce the failure using the serialized JSON shape in the issue. Trace how decorator arguments are captured and how the later model $ref is resolved. Done means an ID first found inside decorator arguments can resolve later without losing the argument metadata.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, csharp, json
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100