Change:
} // must first wait for the dependency to activate <del> currentExtensionGetsGreenLight = false; greenExtensions[ExtensionIdentifier.toKey(depId)] = { </del> <ins> deps.push(this._handleActivationRequest({ </ins> id: depDesc.identifier, reason: currentActivation.reason <del> }; </del> <ins> })); </ins> continue; } // Error condition 1: unknown dependency const currentExtensionFriendlyName = currentExtension.displayName || currentExtension.identifier.value; const error = new Error(`Cannot activate the '${currentExtensionFriendlyName}' extension because it depends on unknown extension '${depId}'`); <ins> const result = this._createAndSaveOperation(currentActivation, currentExtension.displayName, [], new FailedExtension(error)); </ins> this._host.onExtensionActivationError( currentExtension.identifier, error, new MissingExtensionDependency(depId) ); <del> this._activatedExtensions.set(ExtensionIdentifier.toKey(currentExtension.identifier), new FailedExtension(error)); return; </del> <ins> return result; </ins> } <del> if (currentExtensionGetsGreenLight) { greenExtensions[ExtensionIdentifier.toKey(currentExtension.identifier)] = currentActivation; } else { redExtensions.push(currentActivation); } </del> <ins> return this._createAndSaveOperation(currentActivation, currentExtension.displayName, deps, null); </ins> } <del> private _activateExtensions(extensions: ActivationIdAndReason[]): Promise<void> { if (extensions.length === 0) { return Promise.resolve(undefined); } </del> <ins> private _createAndSaveOperation(activation: ActivationIdAndReason, displayName: string | null | undefined, deps: ActivationOperation[], value: ActivatedExtension | null): ActivationOperation { const operation = new ActivationOperation(activation.id, displayName, activation.reason, deps, value, this._host, this._logService); this._operations.set(ExtensionIdentifier.toKey(activation.id), operation); return operation; } } </ins> <del> extensions = extensions.filter((p) => !this._activatedExtensions.has(ExtensionIdentifier.toKey(p.id))); if (extensions.length === 0) { return Promise.resolve(undefined); } </del> <ins> class ActivationOperation { </ins> <del> const greenMap: { [id: string]: ActivationIdAndReason } = Object.create(null), red: ActivationIdAndReason[] = []; </del> <ins> private readonly _barrier = new Barrier(); private _isDisposed = false; </ins> <del> for (let i = 0, len = extensions.length; i < len; i++) { this._handleActivateRequest(extensions[i], greenMap, red); } </del> <ins> public get value(): ActivatedExtension | null { return this._value; } </ins> <del> // Make sure no red is also green for (let i = 0, len = red.length; i < len; i++) { const redExtensionKey = ExtensionIdentifier.toKey(red[i].id); if (greenMap[redExtensionKey]) { delete greenMap[redExtensionKey]; } } </del> <ins> public get friendlyName(): string { return this._displayName || this._id.value; } </ins> <del> const green = Object.keys(greenMap).map(id => greenMap[id]); </del> <ins> constructor( private readonly _id: ExtensionIdentifier, private readonly _displayName: string | null | undefined, private readonly _reason: ExtensionActivationReason, private readonly _deps: ActivationOperation[], private _value: ActivatedExtension | null, private readonly _host: IExtensionsActivatorHost, @ILogService private readonly _logService: ILogService ) { this._initialize(); } </ins> <del> if (red.length === 0) { // Finally reached only leafs! return Promise.all(green.map((p) => this._activateExtension(p.id, p.reason))).then(_ => undefined); } </del> <ins> public dispose(): void { this._isDisposed = true; } </ins> <del> return this._activateExtensions(green).then(_ => { return this._activateExtensions(red); }); </del> <ins> public wait() { return this._barrier.wait(); </ins> } <del> private _activateExtension(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> { const extensionKey = ExtensionIdentifier.toKey(extensionId); </del> <ins> private async _initialize(): Promise<void> { await this._waitForDepsThenActivate(); this._barrier.open(); } </ins> <del> if (this._activatedExtensions.has(extensionKey)) { return Promise.resolve(undefined); </del> <ins> private async _waitForDepsThenActivate(): Promise<void> { if (this._value) { // this operation is already finished return; </ins> } <del> const currentlyActivatingExtension = this._activatingExtensions.get(extensionKey); if (currentlyActivatingExtension) { return currentlyActivatingExtension; </del> <ins> while (this._deps.length > 0) { // remove completed deps for (let i = 0; i < this._deps.length; i++) { const dep = this._deps[i]; if (dep.value && !dep.value.activationFailed) { // the dependency is already activated OK this._deps.splice(i, 1); i--; continue; } if (dep.value && dep.value.activationFailed) { // Error condition 2: a dependency has already failed activation const error = new Error(`Cannot activate the '${this.friendlyName}' extension because its dependency '${dep.friendlyName}' failed to activate`); (<any>error).detail = dep.value.activationFailedError; this._value = new FailedExtension(error); this._host.onExtensionActivationError(this._id, error, null); return; } } if (this._deps.length > 0) { // wait for one dependency await Promise.race(this._deps.map(dep => dep.wait())); } </ins> } <del> const newlyActivatingExtension = this._host.actualActivateExtension(extensionId, reason).then(undefined, (err) => { </del> <ins> await this._activate(); } private async _activate(): Promise<void> { try { this._value = await this._host.actualActivateExtension(this._id, this._reason); } catch (err) { </ins> const error = new Error(); if (err && err.name) { error.name = err.name; } if (err && err.message) { <del> error.message = `Activating extension '${extensionId.value}' failed: ${err.message}.`; </del> <ins> error.message = `Activating extension '${this._id.value}' failed: ${err.message}.`; </ins> } else { <del> error.message = `Activating extension '${extensionId.value}' failed: ${err}.`; </del> <ins> error.message = `Activating extension '${this._id.value}' failed: ${err}.`; </ins> } if (err && err.stack) { error.stack = err.stack; } <ins> // Treat the extension as being empty this._value = new FailedExtension(error); </ins> if (this._isDisposed && errors.isCancellationError(err)) { // It is expected for ongoing activations to fail if the extension host is going down // So simply ignore and don't log canceled errors in this case <del> return new FailedExtension(err); </del> <ins> return; </ins> } <del> this._host.onExtensionActivationError( extensionId, error, null ); this._logService.error(`Activating extension ${extensionId.value} failed due to an error:`); </del> <ins> this._host.onExtensionActivationError(this._id, error, null); this._logService.error(`Activating extension ${this._id.value} failed due to an error:`); </ins> this._logService.error(err); <del> // Treat the extension as being empty return new FailedExtension(err); }).then((x: ActivatedExtension) => { this._activatedExtensions.set(extensionKey, x); this._activatingExtensions.delete(extensionKey); }); this._activatingExtensions.set(extensionKey, newlyActivatingExtension); return newlyActivatingExtension; </del> <ins> } </ins> } }

Discussion:
<!-- Do Not Delete This! bugreporttemplate --<!-- Please read our Rules of Conduct: --<!-- Read our guide about submitting issues: --<!-- Search existing issues to avoid creating duplicates. --<!-- Test using the latest Insiders build to see if your issue has already been fixed: --<!-- Instead of creating your report here, use 'Report Issue' from the 'Help' menu in VS Code to pre-fill useful information. --<!-- Launch with to check. --Does this issue occur when all extensions are disabled?: No <!-- If you answered No above, use 'Help: Start Extension Bisect' from Command Palette to try to identify the cause. --<!-- Issues caused by an extension need to be reported directly to the extension publisher. The 'Help Report Issue' dialog can assist with this. --- VS Code Version: 1.65.0 OS Version: Fedora 35 Steps to Reproduce: extension (v11.10.0) vscode, git extension is not initialized and restart, git extension works again With vscode-icons disabled With vscode-icons enabled
Reproduces with the following extension: : :