Introduction

VS Code's Node.js debugger relies on sourcemaps to map breakpoints in TypeScript source files to the compiled JavaScript output. When sourcemaps are misconfigured or the launch configuration does not match the build output, breakpoints appear as unverified (gray hollow circles) and are never hit:

bash
Breakpoint set on line 15 of src/app.ts shows as "Unverified breakpoint"
Debugger starts but skips all breakpoints

Symptoms

  • Breakpoints show as gray hollow circles (unverified)
  • Debugger starts and runs but never pauses
  • "Breakpoint set but not yet bound" message in the Debug Console
  • Debugger stops in compiled .js files instead of .ts source files
  • Step-through shows JavaScript code instead of TypeScript

Common Causes

  • TypeScript sourceMap not enabled in tsconfig.json
  • outFiles in launch.json does not match the compiled JavaScript output path
  • Breakpoints set before the build is complete (stale sourcemaps)
  • sourceRoot or outDir paths in tsconfig.json do not match the actual directory structure
  • Using ts-node without proper sourcemap configuration

Step-by-Step Fix

  1. 1.Enable sourcemaps in tsconfig.json:
  2. 2.```json
  3. 3.{
  4. 4."compilerOptions": {
  5. 5."target": "ES2020",
  6. 6."module": "commonjs",
  7. 7."outDir": "./dist",
  8. 8."rootDir": "./src",
  9. 9."sourceMap": true,
  10. 10."inlineSources": true,
  11. 11."sourceRoot": "/"
  12. 12.}
  13. 13.}
  14. 14.`
  15. 15.Configure launch.json with the correct outFiles pattern:
  16. 16.```json
  17. 17.{
  18. 18."version": "0.2.0",
  19. 19."configurations": [
  20. 20.{
  21. 21."type": "node",
  22. 22."request": "launch",
  23. 23."name": "Debug TypeScript",
  24. 24."program": "${workspaceFolder}/dist/index.js",
  25. 25."outFiles": [
  26. 26."${workspaceFolder}/dist/**/*.js"
  27. 27.],
  28. 28."preLaunchTask": "tsc: build - tsconfig.json",
  29. 29."sourceMaps": true,
  30. 30."smartStep": true,
  31. 31."skipFiles": [
  32. 32."<node_internals>/**"
  33. 33.]
  34. 34.}
  35. 35.]
  36. 36.}
  37. 37.`
  38. 38.For ts-node debugging (no build step), use this configuration:
  39. 39.```json
  40. 40.{
  41. 41."type": "node",
  42. 42."request": "launch",
  43. 43."name": "Debug TypeScript (ts-node)",
  44. 44."runtimeArgs": ["-r", "ts-node/register"],
  45. 45."args": ["${workspaceFolder}/src/index.ts"],
  46. 46."sourceMaps": true,
  47. 47."cwd": "${workspaceFolder}",
  48. 48."env": {
  49. 49."TS_NODE_FILES": "true"
  50. 50.}
  51. 51.}
  52. 52.`
  53. 53.Verify sourcemaps are generated after building:
  54. 54.```bash
  55. 55.npx tsc
  56. 56.ls dist/
  57. 57.# Should show .js.map files alongside .js files
  58. 58.cat dist/index.js | grep sourceMappingURL
  59. 59.# Should show: //# sourceMappingURL=index.js.map
  60. 60.`
  61. 61.Clean and rebuild to ensure sourcemaps are fresh:
  62. 62.```bash
  63. 63.rm -rf dist/
  64. 64.npx tsc
  65. 65.`
  66. 66.Then start the debugger again.

Prevention

  • Always include "sourceMap": true in your tsconfig.json compiler options
  • Keep launch.json outFiles patterns matching your tsconfig.json outDir
  • Use preLaunchTask to automatically build before debugging
  • Set "smartStep": true to automatically skip generated code without sourcemaps
  • Test breakpoints after any tsconfig.json or build configuration changes
  • Use inlineSources: true to embed source content in sourcemaps for better reliability
  • For monorepos, configure rootDirs in tsconfig.json for correct source mapping
  • Add debugger configuration to your project template so it works out of the box