Change:
} } <ins> private cleanupExpiredTunnelsForRestore() { const keys = this.storageService.keys(StorageScope.PROFILE, StorageTarget.USER).filter(key => key.startsWith(TUNNELS_TO_RESTORE_EXPIRATION)); for (const key of keys) { const expiration = this.storageService.getNumber(key, StorageScope.PROFILE); if (expiration && expiration < Date.now()) { this.tunnelRestoreValue = Promise.resolve(undefined); const storageKey = key.replace(TUNNELS_TO_RESTORE_EXPIRATION, TUNNELS_TO_RESTORE); this.storageService.remove(key, StorageScope.PROFILE); this.storageService.remove(storageKey, StorageScope.PROFILE); } } } </ins> @debounce(1000) private async storeForwarded() { if (this.configurationService.getValue('remote.restoreForwardedPorts')) { <del> const valueToStore = JSON.stringify(Array.from(this.forwarded.values())); if (valueToStore !== this.knownPortsRestoreValue) { this.knownPortsRestoreValue = valueToStore; const key = await this.getStorageKey(); if (key) { this.storageService.store(key, this.knownPortsRestoreValue, StorageScope.PROFILE, StorageTarget.USER); } </del> <ins> const forwarded = Array.from(this.forwarded.values()); const restorableTunnels: RestorableTunnel[] = forwarded.map(tunnel => { return { remoteHost: tunnel.remoteHost, remotePort: tunnel.remotePort, localPort: tunnel.localPort, name: tunnel.name, localAddress: tunnel.localAddress, localUri: tunnel.localUri, protocol: tunnel.protocol, source: tunnel.source, }; }); let valueToStore: string | undefined; if (forwarded.length > 0) { valueToStore = JSON.stringify(restorableTunnels); } const key = await this.getTunnelRestoreStorageKey(); const expirationKey = await this.getRestoreExpirationStorageKey(); if (!valueToStore && key && expirationKey) { this.storageService.remove(key, StorageScope.PROFILE); this.storageService.remove(expirationKey, StorageScope.PROFILE); } else if ((valueToStore !== this.knownPortsRestoreValue) && key && expirationKey) { this.storageService.store(key, valueToStore, StorageScope.PROFILE, StorageTarget.USER); this.storageService.store(expirationKey, Date.now() + RESTORE_EXPIRATION_TIME, StorageScope.PROFILE, StorageTarget.USER); </ins> } <ins> this.knownPortsRestoreValue = valueToStore; </ins> } }

Discussion:
I had to clear settings sync for an unrelated issue and start fresh, but enabling the "UI State" option causes the error below to be continually thrown. If I disable the "UI State" option in settings sync, it starts working again. Type: <bBug</bsettings sync, check all boxes except "UI State" settings sync log, see that it succeeds settings sync config to include UI State VS Code version: Code 1.85.1 (Universal) (, 2023-12-13T09:48:06.308Z) OS version: Darwin arm64 23.2.0 Modes: <details<summarySystem Info</summary </details<details<summaryExtensions (12)</summaryExtensionVersion ------ erb0.0.1 vscode-eslint2.4.2 prettier-vscode10.1.0 codespaces1.16.6 copilot1.148.0 copilot-chat0.11.1 vscode-graphql-syntax1.2.3 endwise1.5.1 remote-containers0.327.0 proto0.0.4 rewrap1.16.3 gitblame10.6.0 (1 theme extensions excluded) </details<details<summaryA/B Experiments</summary</details<!-- generated by issue reporter --
Can you please share the UI state using following steps F1 Export Profile... Select only UI state Export the profile and share it
The exported file is 2.3 MB, and it has some things inside that might be considered sensitive, I'm not sure. Is there a way I can share it privately?
You can share it to me by email - 2.3 MB is way under the limits right?
Just emailed the file, thank you!
I just checked the size limits on the server and it is indeed 2MB caps
Thanks for sharing. I figured out that port forwarding state is taking majority of the size. Hence assigning to
Discussed with and there are 3 easy things I can do to quickly reduce the size: Don't save empty values Add an expiry time to values so they don't live forever Save fewer fields per port in . For example, only tunnels should be stored + restored, so should be removed. So should , , , and .
the limit per resource version is 2mb atm
Are there steps to verify this?

To verify: to a Codespace and forward a port the remote connection the steps in to collect a profile the file created in step 3. Check that the port that you just forwarded in step 1 is listed there under a key and that it doesn't have a value.
For the step, does this mean to stop the codespace?
This is verified. The new port forwarded doesn't have , but I did notice some old ports of mine from old codespaces still having . Not sure if that was expected to be covered.
The behavior you see is expected. I didn't add any cleanup of the old state.