Code change:
private async updateCustomBuiltinExtensionsCache(): Promise<IWebExtension[]> { if (!this._updateCustomBuiltinExtensionsCachePromise) { this._updateCustomBuiltinExtensionsCachePromise = (async () => { <del> // Clear Cache await this.writeCustomBuiltinExtensionsCache(() => []); const { extensions } = await this.readCustomBuiltinExtensionsInfoFromEnv(); if (!extensions.length) { return []; } const galleryExtensionsMap = await this.getExtensionsWithDependenciesAndPackedExtensions(extensions); const missingExtensions = extensions.filter(({ id }) => !galleryExtensionsMap.has(id.toLowerCase())); if (missingExtensions.length) { this.logService.info('Skipping the additional builtin extensions because their compatible versions are not found.', missingExtensions); } </del> <ins> this.logService.info('Updating additional builtin extensions cache'); </ins> const webExtensions: IWebExtension[] = []; <del> await Promise.all([...galleryExtensionsMap.values()].map(async gallery => { try { webExtensions.push(await this.toWebExtensionFromGallery(gallery, { isPreReleaseVersion: gallery.properties.isPreReleaseVersion, preRelease: gallery.properties.isPreReleaseVersion, isBuiltin: true })); } catch (error) { this.logService.info(`Ignoring additional builtin extension ${gallery.identifier.id} because there is an error while converting it into web extension`, getErrorMessage(error)); </del> <ins> const { extensions } = await this.readCustomBuiltinExtensionsInfoFromEnv(); if (extensions.length) { const galleryExtensionsMap = await this.getExtensionsWithDependenciesAndPackedExtensions(extensions); const missingExtensions = extensions.filter(({ id }) => !galleryExtensionsMap.has(id.toLowerCase())); if (missingExtensions.length) { this.logService.info('Skipping the additional builtin extensions because their compatible versions are not found.', missingExtensions); </ins> } <del> })); </del> <ins> await Promise.all([...galleryExtensionsMap.values()].map(async gallery => { try { webExtensions.push(await this.toWebExtensionFromGallery(gallery, { isPreReleaseVersion: gallery.properties.isPreReleaseVersion, preRelease: gallery.properties.isPreReleaseVersion, isBuiltin: true })); } catch (error) { this.logService.info(`Ignoring additional builtin extension ${gallery.identifier.id} because there is an error while converting it into web extension`, getErrorMessage(error)); } })); } </ins> await this.writeCustomBuiltinExtensionsCache(() => webExtensions); return webExtensions; })();

Related discussion:
text: All of a sudden, I no longer have GHPRI installed. When I go into I see Settings Sync removed it 11 hours ago, but I'm 100% sure I never uninstalled it. I know I have Settings Sync enabled in both and are those scenarios doing unexpected things to my settings sync? !
I am sure that 4 days ago I re- the extension. Today, I'm on another machine, and GHPRI is again gone.
Lets sync on this
Closing as I couldn't repro.
I was able to reproduce this issue. will sometimes remove and then readd the GitHub Repositories, Issues & PR, and remotehub extensions, except it doesn't readd the keypair to the config, so when I return to my local installation the extensions will sometimes disappear. Not sure why it doesn't always reinstall though. Sometimes won't readd the missing extensions in time, so it gets removed. When the extensions are without the keypair, the local machine can occasionally readd the missing config and keep the extension installed; other times it won't and the extension is removed. Local machine logs from yesterday: Extension config history: Remote removes extensions: Remote readds extensions, but not marked as installed: After I reinstall the extensions locally: logs from a repro today: Extension sync history: Removed extensions: Readd extensions:
Thanks for logs and info. Reopening for investigation.
I am able to reproduce this with following steps: 1: Install GHPRI pre-release extension and sync .dev: Trigger Sync. Note that this is a builtin extension here. 2: Trigger Sync - Make sure GHPR extension is installed. 1: Uninstall GHPRI extension 2: Trigger Sync - Make sure GHPR extension is uninstalled. .dev: Trigger Sync. Make sure GHPRI extension exists in builtin extensions. 1: Trigger Sync. Nothing changes. 2: Trigger Sync. Nothing changes. This step and above step are important because, even though nothing has changed, these machines update their last sync state to have GHPRI extension has builtin extension. 1: Install GHPRI pre-release extension and sync 2: Trigger Sync GHPRI extension is not installed. Come back to Desktop 1: GHPRI extension is removed.
Improved extensions merging to make sure the builtin extensions are handled properly.