microsoft / microsoft/TypeScript
Panic: nil pointer in NodeList.HasTrailingComma during incremental rebuild (build-mode declaration printer) — 7.0.2 and current nightly
@weswigham y travaille déjà.
Depuis le 10/8/2026.
- Langage dominant
- Go
- Étoiles
- 111k
- Forks
- 14.3k
- Merge moyen
- 2 j 4 h
- PR mergées (30 j)
- 132
Description
## Stack trace
Three worker goroutines panic identically per run; first one below (from `typescript@7.1.0-dev.20260726.1`; `typescript@7.0.2` produces the same frames at the same lines):
```
panic: runtime error: invalid memory address or nil pointer dereference [recovered, repanicked]
[signal SIGSEGV: segmentation violation code=0x2 addr=0xc pc=0x1045fcf98]
goroutine 39500 [running]:
sync.(*WaitGroup).Go.func1.1()
sync/waitgroup.go:251 +0x48
panic({0x1055aae20?, 0x1058a0e60?})
runtime/panic.go:860 +0x12c
github.com/microsoft/typescript-go/internal/ast.(*Node).End(...)
github.com/microsoft/typescript-go/internal/ast/ast.go:194
github.com/microsoft/typescript-go/internal/ast.(*NodeList).HasTrailingComma(...)
github.com/microsoft/typescript-go/internal/ast/ast.go:143
github.com/microsoft/typescript-go/internal/printer.(*Printer).hasTrailingComma(0x23bcc53aadc0?, 0x104c19f78?, 0x23bd0871dae8?)
github.com/microsoft/typescript-go/internal/printer/printer.go:4774 +0x28
github.com/microsoft/typescript-go/internal/printer.(*Printer).emitListRange(0x23bd2c208700, 0x105802028, 0x23bd0741f760, 0x23bd0750cd48, 0xd210, 0x10430f7ec?, 0x20?)
github.com/microsoft/typescript-go/internal/printer/printer.go:4755 +0x2bc
github.com/microsoft/typescript-go/internal/printer.(*Printer).emitList(0x23bd2c208700, 0x105802028, 0x23bd0741f760, 0x23bd0750cd48, 0xd210)
github.com/microsoft/typescript-go/internal/printer/printer.go:4700 +0x94
github.com/microsoft/typescript-go/internal/printer.(*Printer).emitTypeParameters(0x1055c6000?, 0x23bd07542c60?, 0x23bd0741f760?)
github.com/microsoft/typescript-go/internal/printer/printer.go:1506 +0x4c
github.com/microsoft/typescript-go/internal/printer.(*Printer).emitFunctionType(0x23bd2c208700, 0x23bd0741f760)
github.com/microsoft/typescript-go/internal/printer/printer.go:1928 +0x15c
github.com/microsoft/typescript-go/internal/printer.(*Printer).emitTypeNode(0x23bd2c208700, 0x23bd0741f760, 0x871dcb8?)
github.com/microsoft/typescript-go/internal/printer/printer.go:2309 +0x20c
github.com/microsoft/typescript-go/internal/printer.(*Printer).emitTypeNodePreservingExtends(...)
github.com/microsoft/typescript-go/internal/printer/printer.go:2271
github.com/microsoft/typescript-go/internal/printer.(*Printer).emitTypeNodeOutsideExtends(...)
github.com/microsoft/typescript-go/internal/printer/printer.go:2265
github.com/microsoft/typescript-go/internal/printer.(*Printer).emitTypeAnnotation(0x23bd2c208700, 0x23bd0741f760)
github.com/microsoft/typescript-go/internal/printer/printer.go:1516 +0x84
github.com/microsoft/typescript-go/internal/printer.(*Printer).emitPropertySignature(0x23bd2c208700, 0x23bd08134428)
github.com/microsoft/typescript-go/internal/printer/printer.go:1647 +0x78
```
Further up the same stacks: `emitImportTypeNode` (several frames) and `printer.(*Printer).Write`, i.e. build-mode declaration-text printing. Full 3-goroutine dump available on request.
This looks like the same underlying failure as microsoft/typescript-go#3467 (identical bottom frames `ast.(*Node).End` → `NodeList.HasTrailingComma` → `printer.hasTrailingComma` → `emitListRange`), which was hit through the LSP hover path and is closed — this report is the **build-mode / incremental** path, and it still reproduces on the current nightly.
## Steps to reproduce
Reproduces 100% deterministically (5/5 runs) on our project, but only via the **incremental** path:
1. `tsc --noEmit` on a clean tree (writes `tsconfig.tsbuildinfo`) → exits 0.
2. Apply a small refactor. Five different minimal edits all trigger it; the simplest is renaming a generic setter action on one mobx-state-tree store — `updateField(key, value)` → `onChangeField` (16 changed lines across 3 files; the same method name already exists on a sibling store type, and a view elsewhere returns the union of the two store instance types).
3. `tsc --noEmit` again → panic above.
Notes:
- Deleting `tsconfig.tsbuildinfo` between steps 2 and 3 makes the run pass — cold full checks never crash; only the rebuild that reuses build info does.
- `--singleThreaded` crashes identically, so it is not a concurrency race.
- Version matrix on the identical tree + edit: `typescript@7.0.2` **crash**, `typescript@7.1.0-dev.20260726.1` **crash** (recipe re-run natively with the nightly, including rebuilding the buildinfo with it); `@typescript/typescript6@6.0.2` clean, `typescript@5.9.2` clean (same 15 pre-existing unrelated `TS7006` diagnostics before and after the edit, so the edit is type-correct).
- Besides the rename, four other small edits reproduced the same panic on this codebase over the past days: deleting an unused model property + the views reading it; adding a co-located `interface X extends Instance` into a model's own file; swapping a `types.compose` member from a locally-declared model to an imported one; using a shared type-guard for narrowing inside another model's action.
- Environment: macOS arm64 (Darwin 25.5.0), Node v24.14.0, pnpm. Project: Vite + React app, ~2k modules, `mobx-state-tree@7.3.1`. Relevant `compilerOptions`: `strict`, `noEmit: true`, `incremental: true`, `moduleResolution: "bundler"`, `verbatimModuleSyntax`, `isolatedModules`, `skipLibCheck`, `target/module: ESNext`.
The codebase is private, so I can't attach it. I tried to minimize (two MST roots with the same-named generic `keyof typeof self` setter, a view returning the union of both instance types, 60-field models, same incremental+rename recipe) — the synthetic project does not crash, so the trigger seems to need the real project's type complexity. Happy to bisect, run instrumented/debug builds, or capture whatever extra diagnostics would help against the real repo.
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Évaluation
Cette issue n'a pas encore été évaluée.