Skip to content

Data race in module resolver — SIGSEGV in loadModuleFromTargetExportOrImport / OrderedMap.Keys under concurrent goroutines #4060

@mscrivo

Description

@mscrivo

Stack trace

unexpected fault address 0x7263736c65616883
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x2 addr=0x7263736c65616883 pc=0x1046e62c4]

goroutine 125 gp=0x769df0ffe780 m=42 mp=0x769df1601008 [running]:
runtime.throw({0x104c351d4?, 0x769df0d20b20?})
	runtime/panic.go:1229 +0x38
runtime.sigpanic()
	runtime/signal_unix.go:945 +0x21c
github.com/microsoft/typescript-go/internal/module.(*resolutionState).loadModuleFromTargetExportOrImport(...)
	github.com/microsoft/typescript-go/internal/module/resolver.go:823 +0x1f64
github.com/microsoft/typescript-go/internal/module.(*resolutionState).loadModuleFromTargetExportOrImport-range1(...)
	github.com/microsoft/typescript-go/internal/module/resolver.go:838
github.com/microsoft/typescript-go/internal/module.(*resolutionState).loadModuleFromTargetExportOrImport.(*OrderedMap[...]).Keys.func2(...)
	github.com/microsoft/typescript-go/internal/collections/ordered_map.go:138
... (recursive frames through loadModuleFromTargetExportOrImport) ...
github.com/microsoft/typescript-go/internal/module.(*resolutionState).loadModuleFromExports(...)
	github.com/microsoft/typescript-go/internal/module/resolver.go:682 +0x2e4
github.com/microsoft/typescript-go/internal/module.(*resolutionState).loadModuleFromSpecificNodeModulesDirectory(...)
	github.com/microsoft/typescript-go/internal/module/resolver.go:1129 +0x678
github.com/microsoft/typescript-go/internal/module.(*resolutionState).loadModuleFromImmediateNodeModulesDirectory(...)
	github.com/microsoft/typescript-go/internal/module/resolver.go:1028 +0xa8
github.com/microsoft/typescript-go/internal/module.(*resolutionState).loadModuleFromNearestNodeModulesDirectoryWorker.func1(...)
	github.com/microsoft/typescript-go/internal/module/resolver.go:1009 +0x8c
github.com/microsoft/typescript-go/internal/tspath.ForEachAncestorDirectory[...](...)
	github.com/microsoft/typescript-go/internal/tspath/path.go:1068 +0x4c
github.com/microsoft/typescript-go/internal/module.(*resolutionState).loadModuleFromNearestNodeModulesDirectoryWorker(...)
	github.com/microsoft/typescript-go/internal/module/resolver.go:1004 +0x40
github.com/microsoft/typescript-go/internal/module.(*resolutionState).loadModuleFromNearestNodeModulesDirectory(...)
	github.com/microsoft/typescript-go/internal/module/resolver.go:989 +0x1bc
github.com/microsoft/typescript-go/internal/module.(*resolutionState).resolveNodeLikeWorker(...)
	github.com/microsoft/typescript-go/internal/module/resolver.go:563 +0x3b4
github.com/microsoft/typescript-go/internal/module.(*resolutionState).resolveNodeLike(...)
	github.com/microsoft/typescript-go/internal/module/resolver.go:514 +0x94
github.com/microsoft/typescript-go/internal/module.(*Resolver).ResolveModuleName(...)
	github.com/microsoft/typescript-go/internal/module/resolver.go:304 +0x750
github.com/microsoft/typescript-go/internal/compiler.(*fileLoader).resolveImportsAndModuleAugmentations(...)
	github.com/microsoft/typescript-go/internal/compiler/fileloader.go:554 +0x6fc
github.com/microsoft/typescript-go/internal/compiler.(*parseTask).load(...)
	github.com/microsoft/typescript-go/internal/compiler/filesparser.go:158 +0x624
github.com/microsoft/typescript-go/internal/compiler.(*filesParser).start.func1()
	github.com/microsoft/typescript-go/internal/compiler/filesparser.go:290 +0x308
github.com/microsoft/typescript-go/internal/core.(*parallelWorkGroup).Queue.func1()
	github.com/microsoft/typescript-go/internal/core/workgroup.go:40 +0x24
sync.(*WaitGroup).Go.func1()
	sync/waitgroup.go:258 +0x48
runtime.goexit()
	runtime/asm_arm64.s:1447 +0x4
created by sync.(*WaitGroup).Go in goroutine 1

Steps to reproduce

# pnpm monorepo of ~62 workspaces, each with a package.json script:
#   "code-check:tsgo": "tsgo -p ./tsconfig.json --tsBuildInfoFile ./.tsbuildinfo.tsgo"

# Top-level recursive runner (default --workspace-concurrency=4):
pnpm -r --no-bail --aggregate-output code-check:tsgo

# 0–4 random workspaces fail per run. Re-running picks a different set.
# Single-workspace runs in isolation are 100% reliable.

NOTE: This was working perfectly fine for us until not long ago. I don't know which version introduced it, but its broken with 7.0.0-dev.20260518.1 and the latest 7.0.0-dev.20260527.1

Environment

  • macOS 26.5
  • Apple M4 Max, 16 cores
  • Node v24.15.0
  • pnpm 11.3.0

Workaround

running with GOMAXPROCS=1 seems to make it work, albeit 3x slower.

UPDATE: GOMAXPROCS=2 seems to work fine as well, and retains most of the speed.
UPDATE 2: Still have issues with GOMAXPROCS=2

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions