The error, verbatim
Jump to the fix ↓C:\project\node_modules\ts-node\dist\configuration.js:91
const { fileExists = ts.sys.fileExists, readFile = ts.sys.readFile, ... } = rawApiOptions;
^
TypeError: Cannot read properties of undefined (reading 'fileExists')
at readConfig (C:\project\node_modules\ts-node\dist\configuration.js:91:33)
at findAndReadConfig (C:\project\node_modules\ts-node\dist\configuration.js:50:84)
at phase3 (C:\project\node_modules\ts-node\dist\bin.js:254:67)
Tested on
- ts-node
- 10.9.2
- TypeScript
- 6.0.3, 7.0.2, 7.1.0-dev.20260922
- Node
- 24.14.0
- OS
- Windows 11 Pro
Contents
Nothing in your project changed. Someone ran npm install, or added typescript to a fresh project, and now every ts-node command dies in ts-node’s own configuration.js, before your code is even read.
The fix
Check which TypeScript you have:
npm ls typescriptIf it’s 7.x, that’s the cause. Pick one of these:
1. Run TypeScript 7 and 6 side by side (recommended, and what Microsoft’s TypeScript 7.0 announcement suggests). tsc stays on 7; ts-node gets the 6.x API it needs:
npm install -D "@typescript/native@npm:typescript@7.0.2" "typescript@npm:@typescript/typescript6@^6.0.2"2. Stay on TypeScript 6 (simplest, but you give up TypeScript 7 for builds):
npm i -D typescript@6.0.33. Keep TypeScript 7 and drop ts-node for tsx:
npm i -D tsx
npx tsx src/index.ts4. Keep TypeScript 7 and use Node itself, if you’re on Node 22.18 or newer:
node src/index.tsYour tsc build is unaffected by all of this: TypeScript 7.0.2’s compiler ran the same project with no errors.
Why it happens
TypeScript 7 is the compiler rewritten in Go. The command line behaves as before, but the npm package is no longer a JavaScript library you can import. This is the whole story, in two commands:
# TypeScript 6.0.3
node -p "Object.keys(require('typescript')).length" # 2248 exports
node -p "typeof require('typescript').sys" # object
# TypeScript 7.0.2
node -p "Object.keys(require('typescript'))" # [ 'version', 'versionMajorMinor' ]
node -p "typeof require('typescript').sys" # undefined
ts-node reads your tsconfig.json through that API. Its line is:
const { fileExists = ts.sys.fileExists, ... } = rawApiOptions;
With ts.sys now undefined, reading .fileExists from it throws, which is why the stack trace contains only ts-node and no file of yours.
Which versions break
| TypeScript | require('typescript').sys |
ts-node 10.9.2 |
|---|---|---|
| 6.0.3 | object | runs |
7.0.2 (current latest) |
undefined | crashes |
| 7.1.0-dev.20260922 | undefined | crashes |
npm install typescript today gives you 7.0.2, because it’s the latest tag. That’s why this reaches projects nobody touched: a fresh clone, a CI cache miss, or a teammate who installed without a lockfile.
The nightly for 7.1 still had no importable API when I tested it, so this isn’t a wait-a-week problem.
What didn’t work
It isn’t only ts-node
Anything that loads the TypeScript compiler as a library hits the same wall. I’ve since reproduced it in ts-loader (webpack), which fails with the identical reading 'fileExists' message, plus TypeDoc, ts-jest and typescript-eslint; the results are in TypeScript 7 compatibility: 9 tools tested. Other projects have open reports too: ts-patch, Medusa’s config loader and Cypress spec preprocessing all have open reports. The ts-node one is issue #2174, opened the day TypeScript 7 shipped, with no maintainer answer yet. The ts-patch, Medusa and Cypress cases are linked as reports; I haven’t reproduced those three.
If you maintain a tool that imports typescript, this is the version to pin before your users find out for you.
Run it yourself
The project I used is on GitHub, so you can trigger the error on your own machine in under a minute:
git clone https://github.com/nils44344/node-ts-error-repros
cd node-ts-error-repros/04-ts-node-typescript-7
npm install && npm run repro
How this was tested
A CommonJS project with a three-line TypeScript file, ts-node@10.9.2 and Node 24.14.0, installed fresh and then run against TypeScript 6.0.3, 7.0.2 and the 7.1.0 nightly, switching only the TypeScript version between runs. Every result above, including the four fixes, is the real terminal output.
— N.K., end of entry No.016