Change:
// If a task is missing the problem matcher the promise will never complete, so we need to have a workaround #35340 let taskStarted = false; <ins> const store = new DisposableStore(); </ins> const getTaskKey = (t: Task) => t.getKey() ?? t.getMapKey(); const taskKey = getTaskKey(task); <del> const inactivePromise: Promise<ITaskSummary | null> = new Promise((c) => once(e => { // When a task isBackground it will go inactive when it is safe to launch. // But when a background task is terminated by the user, it will also fire an inactive event. // This means that we will not get to see the real exit code from running the task (undefined when terminated by the user). // Catch the ProcessEnded event here, which occurs before inactive, and capture the exit code to prevent this. return (e.kind === TaskEventKind.Inactive || (e.kind === TaskEventKind.ProcessEnded && e.exitCode === undefined)) && getTaskKey(e.__task) === taskKey; }, this.taskService.onDidStateChange)(e => { taskStarted = true; c(e.kind === TaskEventKind.ProcessEnded ? { exitCode: e.exitCode } : null); })); const promise: Promise<ITaskSummary | null> = this.taskService.getActiveTasks().then(async (tasks): Promise<ITaskSummary | null> => { </del> <ins> const inactivePromise: Promise<ITaskSummary | null> = new Promise((resolve) => store.add( onceFilter(this.taskService.onDidStateChange, e => { // When a task isBackground it will go inactive when it is safe to launch. // But when a background task is terminated by the user, it will also fire an inactive event. // This means that we will not get to see the real exit code from running the task (undefined when terminated by the user). // Catch the ProcessEnded event here, which occurs before inactive, and capture the exit code to prevent this. return (e.kind === TaskEventKind.Inactive || (e.kind === TaskEventKind.ProcessEnded && e.exitCode === undefined)) && getTaskKey(e.__task) === taskKey; })(e => { taskStarted = true; resolve(e.kind === TaskEventKind.ProcessEnded ? { exitCode: e.exitCode } : null); }), )); store.add( onceFilter(this.taskService.onDidStateChange, e => ((e.kind === TaskEventKind.Active) || (e.kind === TaskEventKind.DependsOnStarted)) && getTaskKey(e.__task) === taskKey )(() => { // Task is active, so everything seems to be fine, no need to prompt after 10 seconds // Use case being a slow running task should not be prompted even though it takes more than 10 seconds taskStarted = true; }) ); const didAcquireInput = store.add(new Emitter<void>()); store.add(onceFilter( this.taskService.onDidStateChange, e => (e.kind === TaskEventKind.AcquiredInput) && getTaskKey(e.__task) === taskKey )(() => didAcquireInput.fire())); const taskDonePromise: Promise<ITaskSummary | null> = this.taskService.getActiveTasks().then(async (tasks): Promise<ITaskSummary | null> => { </ins> if (tasks.find(t => getTaskKey(t) === taskKey)) { <ins> didAcquireInput.fire(); </ins> // Check that the task isn't busy and if it is, wait for it const busyTasks = await this.taskService.getBusyTasks(); if (busyTasks.find(t => getTaskKey(t) === taskKey)) {

Discussion:
Clone and npm install. Hit F5, it never starts: <img width="484" alt="image" src=""I am on macOS.
This is probably because a prelaunch task is still running / your problem matchers haven't matched anything. Please make sure you have the right problem matchers installed, otherwise I suggest opening issues for them if they don't match correctly.
Would be great if debug could give me a hint.
Will keep open to track it, it's not a rare problem
We should also keep the terminal open if the task fails, currently it closes immediately which can be confusing
Would also be nice if we could cancel the pending launch attempt, e.g. by showing the debug toolbar immediately and disabling all buttons except the stop button. Right now when I get into this state I end up just reloading the whole window and incurring the pain of all extensions reactivating, which takes several seconds on my machine (git, TS etc)
After 10 seconds we'll show !
<!-- UNABLETOLOCATECOMMITMESSAGE repo --Issue marked as unreleased but unable to locate closing commit in repo history. If this was closed in a separate repo you can add the label directly, or comment .
<!-- UNABLETOLOCATECOMMITMESSAGE --Issue marked as unreleased but unable to locate closing commit in issue timeline. You can manually reference a commit by commenting , or directly add the label if you know this has already been releaased