microsoft / microsoft/typespec

[Bug]: [http-server-csharp] Model with a `Record<unknown>[]` property generates C# that does not compile (missing `using System.Text.Json.Nodes;`)

Open Beginner friendly
#11,733 2 comments 1 reaction 0 assignees View on GitHub
bug emitter:service:csharp triaged:core
Dominant language
Java
Stars
5.9k
Forks
394
Avg merge
1d 23h
Merged PRs (30d)
104

Description

### Describe the bug

**Package**: `@typespec/http-server-csharp` `0.58.0-alpha.30`

## Description

A model property typed as an **array of** `Record` is emitted as `JsonObject[]`, but the
generated model file does not include `using System.Text.Json.Nodes;`, so the generated project
fails to compile with `CS0246: The type or namespace name 'JsonObject' could not be found`.

A property typed as `Record` *directly* (non-array) works correctly — the using
directive is emitted.

### Reproduction

## Repro

[Playground link](https://typespec.io/playground/?tspconfig=ZW1pdDoKICAtICJAdHlwZXNwZWMvaHR0cC1zZXJ2ZXItY3NoYXJwIgo%3D&c=aW1wb3J0ICJAdHlwZXNwZWMvaHR0cCI7DQp1c2luZyBIdHRwOw0KDQpAc2VydmljZSgjeyB0aXRsZTogIlJlcHJvIiB9KQ0KbmFtZXNwYWNlIMUVxTNtb2RlbCBEYXRhc2V0Um93IGlzIFJlY29yZDx1bmtub3duPssoUGFnZSB7DQogIGl0ZW1zOss5W107IC8vIGFycmF5IG9m0EUgLT4gSnNvbk9iamVjdFtdDQp9xFdAcm91dGUoIi9yb3dzIikNCmludGVyZuUApG93c8ZsQGdldCBsaXN0KCk65QCDO8U%2B&vs=%7B%7D)

```typespec
import "@typespec/http";
using Http;

@service(#{ title: "Repro" })
namespace Repro;

model DatasetRow is Record;

model Page {
items: DatasetRow[]; // array of Record -> JsonObject[]
}

@route("/rows")
interface Rows {
@get list(): Page;
}
```

## Actual output

`generated/models/Page.cs` (note: no `System.Text.Json.Nodes`):

```csharp
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
using TypeSpec.Helpers;
using TypeSpec.Helpers.JsonConverters;

namespace Repro
{
public partial class Page
{
[JsonPropertyName("items")]
public required JsonObject[] Items { get; set; } // CS0246
}
}
```

## Expected output

The same file with `using System.Text.Json.Nodes;` included, as already happens when a property
is typed `Record` without the array.

## Root cause

`modelNeedsJsonNodes` in `src/components/models/model-helpers.ts` decides whether a model file
gets the `System.Text.Json.Nodes` using. It checks whether a property's type is a
`Record` model, but never unwraps array types, so `Record[]` (an Array model
whose indexer value is the Record) is missed — while the type-expression emission for the same
property does produce `JsonObject[]`.

## Suggested fix

Unwrap array indexers before the record check (loop so nested arrays are covered):

```ts
/** Returns true if any property of the model uses Record (mapped to JsonObject). */
export function modelNeedsJsonNodes($: Typekit, model: Model): boolean {
for (const prop of model.properties.values()) {
// Unwrap array types: Record[] emits JsonObject[] and needs JsonNodes too
let type = prop.type;
while (type.kind === "Model" && $.array.is(type) && type.indexer?.value) {
type = type.indexer.value;
}
if (type.kind === "Model" && $.record.is(type)) {
// Only need JsonNodes for Record (maps to JsonObject)
const valueType = type.indexer?.value;
if (valueType?.kind === "Intrinsic" && valueType.name === "unknown") return true;
}
}
return false;
}
```

We are running this change as a `patch-package` patch against the compiled `dist` output and can
confirm it fixes the compilation error without affecting the existing non-array behavior.

### Checklist

- [x] Follow our [Code of Conduct](https://github.com/microsoft/typespec/blob/main/CODE_OF_CONDUCT.md)
- [x] Check that there isn't already an issue that request the same bug to avoid creating a duplicate.
- [x] Check that this is a concrete bug. For Q&A open a [GitHub Discussion](https://github.com/Microsoft/typespec/discussions).
- [x] The provided reproduction is a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug.

Contributor guide

Open the contributing guide

Research direction

Start in src/components/models/model-helpers.ts at modelNeedsJsonNodes and inspect how array model indexers are handled before the Record check. Reproduce the issue with the linked Playground example, then verify that generated/models/Page.cs includes System.Text.Json.Nodes and that the generated project compiles without changing direct Record behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, typescript
Domain
backend, tooling
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.