Every time you press F5, there are likely steps you need to do first: compile your TypeScript, build a binary, start a database, or run a linter. After debugging, you may need to clean up: stop services, remove temp files, or reset test data.
VS Code can automate these steps with two fields in your launch configuration: preLaunchTask and postDebugTask.
Run a task before debugging with preLaunchTask
Add the preLaunchTask field to any launch configuration. Its value must match the label of a task in your tasks file.
{
"type": "node",
"request": "launch",
"name": "Launch with Build",
"program": "${workspaceFolder}/dist/server.js",
"preLaunchTask": "npm: build"
}When you press F5, VS Code first runs the npm: build task. It waits for the task to finish. If the task succeeds, the debugger starts. If the task fails, the debugger does not start and VS Code shows the failure output in the terminal.
This guarantees you never debug stale code. The build runs every time, and a failed build blocks the debug session.
Define the task in your tasks file
Your tasks file needs an entry whose label matches the preLaunchTask value. This task definition tells VS Code what command to run and groups it as a build task.
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "build",
"group": "build",
"label": "npm: build"
}
]
}For a custom shell command, use the shell type instead of npm. This runs any command your terminal can execute:
{
"version": "2.0.0",
"tasks": [
{
"label": "Compile TypeScript",
"type": "shell",
"command": "npx tsc",
"group": "build"
}
]
}Then reference it as "preLaunchTask": "Compile TypeScript" in your launch configuration.
Run a task after debugging with postDebugTask
The postDebugTask field works the same way but runs after the debug session ends. Use it for cleanup.
{
"type": "node",
"request": "launch",
"name": "Launch with Cleanup",
"program": "${workspaceFolder}/server.js",
"postDebugTask": "Clean up temp files"
}Now define what that cleanup task actually does. This shell task removes temporary files from your workspace when the debug session finishes:
{
"label": "Clean up temp files",
"type": "shell",
"command": "rm -rf ${workspaceFolder}/tmp/*"
}The cleanup task runs whether the debug session ends normally or you stop it manually. It runs in a new terminal and its output appears briefly before the terminal closes.
Run multiple tasks before debugging
If you need to run several tasks before debugging, create a compound task in your tasks file. A compound task runs multiple tasks either in parallel or in sequence.
Define the individual tasks first. A lint task runs eslint on your project. A compile task runs the TypeScript compiler. Both are standard shell tasks.
Then create a compound task that depends on both. Set dependsOrder to sequence to run them one after another, or omit it to run them in parallel.
{
"label": "Pre-Debug Setup",
"dependsOn": ["Lint", "Compile"],
"dependsOrder": "sequence"
}Reference the compound task in your launch configuration with "preLaunchTask": "Pre-Debug Setup".
Use background tasks as pre-launch tasks
Some tools run in the background, like a TypeScript compiler in watch mode or a development server. You can use these as pre-launch tasks, but they need a problemMatcher so VS Code knows when they are ready.
A background task without a problemMatcher never signals completion. VS Code waits forever and the debugger never starts. Add a background problemMatcher that detects the "ready" message in the task output.
{
"type": "npm",
"script": "watch",
"isBackground": true,
"problemMatcher": "$tsc-watch",
"label": "npm: watch"
}The $tsc-watch problemMatcher is built into VS Code. It detects when the TypeScript compiler prints "Compilation complete. Watching for file changes." and signals the task as ready.
Practical workflows
TypeScript development
Compile TypeScript before debugging, then run the compiled JavaScript. Your launch configuration gets a pre-launch build task that runs tsc. Set outFiles so the debugger can find the compiled JavaScript.
Full-stack with Docker
Start Docker containers before debugging, stop them after. Use preLaunchTask to run docker-compose up and postDebugTask to run docker-compose down. This keeps your database available only while you are debugging. For a client and server that both need to start together, see compound configurations.
Database migration before testing
Run migrations before debugging to ensure the schema is current. Set preLaunchTask to your migration script. If a migration fails, the debugger does not start and you catch schema issues before testing.
Troubleshooting
The pre-launch task never finishes
Check that the task is not marked as a background task without a problemMatcher. Background tasks need a problemMatcher to signal completion. If the task is not meant to run in the background, remove isBackground: true or set it to false.
"Could not find the task" error
The label in preLaunchTask must match the label in your tasks file exactly, including case and spaces. Open your tasks file and copy the label directly. Also check that the tasks file is in the .vscode folder at the workspace root and is valid JSON.
The task runs but the debugger starts before it finishes
This happens with background tasks that lack a problemMatcher. VS Code sees the task start and immediately considers it done. Add a background problemMatcher or use a non-background task that exits when complete.
The post-debug task does not run
postDebugTask runs after the debug session fully terminates. If another session is still active, the task waits. Also check that the task label matches exactly, including case.
Rune AI
Key Insights
- Add preLaunchTask to run a task before the debugger starts. The task label must match exactly a task in your tasks file.
- Add postDebugTask to run a task after the debug session ends. Use it for cleanup: stop Docker containers, remove temp files, or reset test data.
- If the pre-launch task fails, the debugger does not start. This guarantees you never debug stale code.
- Background tasks used as preLaunchTask must have a problemMatcher so VS Code knows when initialization is complete.
- Create a compound task to run multiple tasks before debugging. Reference the compound task's label in preLaunchTask.
Frequently Asked Questions
Can I use a background task as a preLaunchTask?
What happens if my preLaunchTask fails?
Can I have multiple pre-launch tasks?
Conclusion
preLaunchTask and postDebugTask turn your debug configuration into an automated workflow. Build your code before debugging, start dependency services, run database migrations, and clean up temp files after the session ends. Define the task once in your tasks file and reference it by label from your launch configuration. For projects with multiple services, combine this with compound configurations to debug everything from one action.
More in this topic
How to Use VS Code with WSL 2 on Windows
Run VS Code connected to Windows Subsystem for Linux so you can develop in a full Linux environment with native tools, terminals, and debugging, all from Windows.
20 Best VS Code Extensions for Web Developers in 2026
Twenty carefully chosen VS Code extensions every web developer should know. Covers formatting, linting, frameworks, debugging, Git, and developer experience.
How to Install, Disable, Update, and Uninstall VS Code Extensions
Learn how to install, disable, update, and uninstall VS Code extensions from the Marketplace and the command line. Step-by-step instructions for every action.