Change:
Issue Type: <bBug</bto a remote machine with the ssh extension the jupyter extension on the remote machine (I also have it installed locally) the extension, reload the window, then re-enable Result: Error: The extension has to be uninstalled and reinstalled to get it to load again VS Code version: Code - Insiders 1.69.0-insider (, 2022-06-24T06:32:08.615Z) OS version: WindowsNT x64 10.0. Restricted Mode: No Remote OS version: Linux x64 5.13.0-1021-azure <details<summarySystem Info</summary </details<details<summaryExtensions (10)</summaryExtensionVersion ------ Bookmarks13.3.0 tsl-problem-matcher0.6.2 vscode-language-pack-de1.69. jupyter-keymap1.0.0 remote-containers0.240.0 remote-ssh0.83. remote-wsl0.66.3 jupyter2022.6. jupyter-keymap1.0.0 jupyter-renderers1.0.8 </details<details<summaryA/B Experiments</summary</details<!-- generated by issue reporter --
Hi there, I raised a duplicate issue and was asked if I would try "Insiders" to see if it reproed. I installed Insiders and it did not repro so seems fixed. What I don't understand is whether I should keep Insiders installed, or uninstall my normal VSCode and use it instead. I use VSCode on WSL. There was no explanation of what to do with Insiders. I am going on the assumption that I will uninstall it and wait for this to make it into a mainline VSCode update.
Right and this fix is available in VS Code (stable) now.
I don't think this is actually fixed. Maybe it started working for due to doing a reinstall (switching to Insiders)? I did a brand new install of Code (first time on this machine) yesterday Version 1.69.1, Date: 2022-07-12 (2 days ago) Installed ssh extension and connected remote Source code did not have any Git change information (no line markers for lines that have changed) recommended disabling built-in 'Git' and re-enabling it Same issue happened when I tried to re-enable the disabled Git extension: "Cannot change enablement of Git Base extension because of its extension kind" Strange workaround: Click 'Enable for Workspace' Then click 'Enable' It appears to be enabled (although the source code still does not show git change that's a different issue)
Can you please provide a gif to get better understanding of what is happening?
Here are the steps in the video: Open remote connection using ssh extension Go to extensions, filter by "Built In" Select Git, and Disable Reload Go to extensions, select Git Try Enabling (fails) Go to Explorer, open a workspace Go to extensions, select Git Try Enabling (fails) Enable for workspace (success) Try Enabling (success) !

Discussion:
throw new Error(localize('cannot change enablement environment', "Cannot change enablement of {0} extension because it is enabled in environment", extension.manifest.displayName || extension.identifier.id)); } <del> switch (this.getEnablementState(extension)) { </del> <ins> this.throwErrorIfEnablementStateCannotBeChanged(extension, this.getEnablementState(extension), donotCheckDependencies); } private throwErrorIfEnablementStateCannotBeChanged(extension: IExtension, enablementStateOfExtension: EnablementState, donotCheckDependencies?: boolean): void { switch (enablementStateOfExtension) { </ins> case EnablementState.DisabledByEnvironment: throw new Error(localize('cannot change disablement environment', "Cannot change enablement of {0} extension because it is disabled in environment", extension.manifest.displayName || extension.identifier.id)); case EnablementState.DisabledByVirtualWorkspace:

} private getExtensionsToEnableRecursively(extensions: IExtension[], allExtensions: ReadonlyArray<IExtension>, enablementState: EnablementState, options: { dependencies: boolean; pack: boolean }, checked: IExtension[] = []): IExtension[] { <ins> if (!options.dependencies && !options.pack) { return []; } </ins> const toCheck = extensions.filter(e => checked.indexOf(e) === -1); <del> if (toCheck.length) { for (const extension of toCheck) { checked.push(extension); </del> <ins> if (!toCheck.length) { return []; } for (const extension of toCheck) { checked.push(extension); } const extensionsToDisable: IExtension[] = []; for (const extension of allExtensions) { // Extension is already checked if (checked.some(e => areSameExtensions(e.identifier, extension.identifier))) { continue; </ins> } <del> const extensionsToDisable = allExtensions.filter(i => { if (checked.indexOf(i) !== -1) { return false; </del> <ins> const enablementStateOfExtension = this.getEnablementState(extension); // Extension enablement state is same as the end enablement state if (enablementStateOfExtension === enablementState) { continue; } // Check if the extension is a dependency or in extension pack if (extensions.some(e => (options.dependencies && e.manifest.extensionDependencies?.some(id => areSameExtensions({ id }, extension.identifier))) || (options.pack && e.manifest.extensionPack?.some(id => areSameExtensions({ id }, extension.identifier))))) { const index = extensionsToDisable.findIndex(e => areSameExtensions(e.identifier, extension.identifier)); // Extension is not aded to the disablement list so add it if (index === -1) { extensionsToDisable.push(extension); </ins> } <del> if (this.getEnablementState(i) === enablementState) { return false; </del> <ins> // Extension is there already in the disablement list. else { try { // Replace only if the enablement state can be changed this.throwErrorIfEnablementStateCannotBeChanged(extension, enablementStateOfExtension, true); extensionsToDisable.splice(index, 1, extension); } catch (error) { /*Do not add*/ } </ins> } <del> return (options.dependencies || options.pack) && extensions.some(extension => (options.dependencies && extension.manifest.extensionDependencies?.some(id => areSameExtensions({ id }, i.identifier))) || (options.pack && extension.manifest.extensionPack?.some(id => areSameExtensions({ id }, i.identifier))) ); }); if (extensionsToDisable.length) { extensionsToDisable.push(...this.getExtensionsToEnableRecursively(extensionsToDisable, allExtensions, enablementState, options, checked)); </del> } <del> return extensionsToDisable; </del> } <del> return []; </del> <ins> if (extensionsToDisable.length) { extensionsToDisable.push(...this.getExtensionsToEnableRecursively(extensionsToDisable, allExtensions, enablementState, options, checked)); } return extensionsToDisable; </ins> } private _setUserEnablementState(extension: IExtension, newState: EnablementState): Promise<boolean> {

assert.deepStrictEqual(testObject.getEnablementState(extension), EnablementState.DisabledByVirtualWorkspace); }); <ins> test('test enable a remote workspace extension and local ui extension that is a dependency of remote', async () => { instantiationService.stub(IExtensionManagementServerService, anExtensionManagementServerService(anExtensionManagementServer('vscode-local', instantiationService), anExtensionManagementServer('vscode-remote', instantiationService), null)); const localUIExtension = aLocalExtension2('pub.a', { main: 'main.js', extensionKind: ['ui'] }, { location: URI.file(`pub.a`) }); const remoteUIExtension = aLocalExtension2('pub.a', { main: 'main.js', extensionKind: ['ui'] }, { location: URI.file(`pub.a`).with({ scheme: 'vscode-remote' }) }); const target = aLocalExtension2('pub.b', { main: 'main.js', extensionDependencies: ['pub.a'] }, { location: URI.file(`pub.b`).with({ scheme: 'vscode-remote' }) }); testObject = new TestExtensionEnablementService(instantiationService); installed.push(localUIExtension, remoteUIExtension, target); await testObject.setEnablement([target, localUIExtension], EnablementState.DisabledGlobally); await testObject.setEnablement([target, localUIExtension], EnablementState.EnabledGlobally); assert.ok(testObject.isEnabled(target)); assert.ok(testObject.isEnabled(localUIExtension)); assert.strictEqual(testObject.getEnablementState(target), EnablementState.EnabledGlobally); assert.strictEqual(testObject.getEnablementState(localUIExtension), EnablementState.EnabledGlobally); }); test('test enable a remote workspace extension also enables its dependency in local', async () => { instantiationService.stub(IExtensionManagementServerService, anExtensionManagementServerService(anExtensionManagementServer('vscode-local', instantiationService), anExtensionManagementServer('vscode-remote', instantiationService), null)); const localUIExtension = aLocalExtension2('pub.a', { main: 'main.js', extensionKind: ['ui'] }, { location: URI.file(`pub.a`) }); const remoteUIExtension = aLocalExtension2('pub.a', { main: 'main.js', extensionKind: ['ui'] }, { location: URI.file(`pub.a`).with({ scheme: 'vscode-remote' }) }); const target = aLocalExtension2('pub.b', { main: 'main.js', extensionDependencies: ['pub.a'] }, { location: URI.file(`pub.b`).with({ scheme: 'vscode-remote' }) }); testObject = new TestExtensionEnablementService(instantiationService); installed.push(localUIExtension, remoteUIExtension, target); await testObject.setEnablement([target, localUIExtension], EnablementState.DisabledGlobally); await testObject.setEnablement([target], EnablementState.EnabledGlobally); assert.ok(testObject.isEnabled(target)); assert.ok(testObject.isEnabled(localUIExtension)); assert.strictEqual(testObject.getEnablementState(target), EnablementState.EnabledGlobally); assert.strictEqual(testObject.getEnablementState(localUIExtension), EnablementState.EnabledGlobally); }); </ins> test('test canChangeEnablement return false when extension is disabled in virtual workspace', () => { const extension = aLocalExtension2('pub.a', { capabilities: { virtualWorkspaces: false } }); instantiationService.stub(IWorkspaceContextService, 'getWorkspace', <IWorkspace>{ folders: [{ uri: URI.file('worskapceA').with(({ scheme: 'virtual' })) }] });