Skip to content

fix(desktop): one unreadable value in desktop-settings.json no longer resets every desktop setting - #28682

Closed
only21mil wants to merge 3 commits into
pingdotgg:mainfrom
only21mil:fix/audit-m060
Closed

only21mil wants to merge 3 commits into
pingdotgg:mainfrom
only21mil:fix/audit-m060

Conversation

@only21mil

@only21mil only21mil commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Problem

If desktop-settings.json holds one value this build can't read (for example "updateChannel": "beta" from a hand edit or another build), the desktop app ignores the whole file and starts from defaults. The next settings save writes those defaults over the file, so the user's local environment, network access, Tailscale, WSL and window settings are gone for good.

Change

The strict document decode in readSettings failed before the field-by-field normalizeDesktopSettingsDocument could run. It now drops a key whose value it can't read, by mapping the existing document schema's fields through Schema.catchDecoding, so that field falls back to its default and every other field still loads. Malformed JSON, or a file that isn't an object, still falls back to defaults as before.

Scope

A bug fix for lost data. It is a small, focused fix for an obvious bug, so it needs no issue: one bad field should not throw away the other valid settings. Possibly related: #26144 (localEnvironmentEnabled: false disappeared), but that report doesn't say what the file held, so this PR doesn't claim to fix it.

Verification

To see it on Linux (desktop app):

  1. Write { "localEnvironmentEnabled": false, "updateChannel": "beta" } to desktop-settings.json.
  2. Start the desktop app and open Settings → Environments.
  3. On main Local environment is on, and after a close the saved file has lost localEnvironmentEnabled; with this PR it stays off and is kept.

Linux desktop app built with vp run build:desktop from main 65c0195b46, then from this branch at d388a0a3d2 (this PR merged with that main): unpackaged Electron 44 under Xvfb, an isolated home, environment named "Test machine", the same file written before each launch. Settings opened by URL over the debugging port; the app closed with Alt+F4 through the window manager (X input). The extended DesktopAppSettings.test.ts load case fails with main's DesktopAppSettings.ts and passes here (13/13).

Main 65c0195: Local environment is on after loading the file

Main 65c0195b46: Local environment is on after loading the file

This PR at d388a0a: Local environment stays off

This PR at d388a0a3d2: Local environment stays off

The saved file after the close, main 65c0195b46:

## desktop-settings.json after quit:
{"mainWindowBounds":{"x":170,"y":60,"width":1100,"height":780}}

This PR at d388a0a3d2:

## desktop-settings.json after quit:
{"localEnvironmentEnabled":false,"mainWindowBounds":{"x":170,"y":60,"width":1100,"height":780}}

Not checked:

  • macOS: not run. Windows: not run.
  • Packaged installers, and settings files from real older or newer builds. The runs used a hand-written unreadable value.
The change in full and the tests

normalizeDesktopSettingsDocument already falls back field by field. The strict document decode in readSettings fails first, though, and Effect.orElseSucceed swaps in the defaults for every field. The document decode now drops a key whose value it can't read (for example "updateChannel": "beta" or "wslOnly": "yes"), so that field falls back to its default and every other field still loads. Field types, defaults, the normalizer and the write path are unchanged. Mapping the fields, instead of rewriting each one, also covers any field added later. A value the build can't read is still not kept: the next save rewrites the file from the loaded settings, the same as for values the normalizer already replaces, such as an out-of-range Tailscale port.

In the desktop runs above, main's saved file held only mainWindowBounds after the close; with this PR it kept "localEnvironmentEnabled": false, and updateChannel was dropped.

Possibly related: #26144, where localEnvironmentEnabled: false disappeared from desktop-settings.json. The run above shows the same symptom from a file with one unreadable value, but that report doesn't say what the file held, so this PR doesn't claim to fix it.

Prior PRs

None make this fix. #3265, #3379 and #3432 by juliusmarminge reworked how desktop settings errors are structured and diagnosed. #26757 by t3dotgg adds a field to the same document schema and benefits from this without changes.

Generated with Claude Opus 5.5 and GPT-6.1 Terra and GPT-6.1 Sol in T3 Code Nightly

… resets every desktop setting

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@github-actions github-actions Bot added vouch:unvouched Author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Nov 1, 2026
@macroscopeapp

macroscopeapp Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at a3ca0bd

Macroscope's review found this PR approvable — Unreadable desktop settings now fall back individually, preserving other saved preferences. Existing defaults and validation remain unchanged, with no new operational behavior introduced.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

Desktop settings decoding now omits fields that cannot be decoded instead of failing the entire document. Tests check that unsupported values use defaults, valid values load, and other loaded settings remain after a server exposure mode update.

Changes: Desktop settings

Layer / File(s) Summary
Per-field settings decoding
apps/desktop/src/settings/DesktopAppSettings.ts, apps/desktop/src/settings/DesktopAppSettings.test.ts
The decoder handles unreadable fields independently. Tests check defaults for unsupported updateChannel and wslOnly values, preserve localEnvironmentEnabled: false, and verify that other loaded settings remain after a server exposure mode update.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested labels: bugfix

Suggested reviewers: juliusmarminge, t3dotgg

Merge Risk: Minimal · up to d388a

This change keeps one invalid desktop setting from resetting all the others. No actionable merge-blocking risk was found. Packaged installers and settings files from other builds were not verified.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title states the main change: one unreadable value in desktop-settings.json no longer resets every desktop setting. The raw summary describes per-field decoding middleware (DropUnreadableKey) in D…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description follows the repository template closely. It has all four sections: Problem, Change, Scope, and Verification. The Problem section states the bug: one unreadable value in desktop-setting…
Full details: Title check

Explanation

The title states the main change: one unreadable value in desktop-settings.json no longer resets every desktop setting. The raw summary describes per-field decoding middleware (DropUnreadableKey) in DesktopAppSettings.ts that drops only the unreadable key, which matches the title. The title is clear, specific, and follows the conventional commit format used in the repository template.

Full details: Description check

Explanation

The description follows the repository template closely. It has all four sections: Problem, Change, Scope, and Verification. The Problem section states the bug: one unreadable value in desktop-settings.json makes the app discard the whole file and reset to defaults. The Change section explains that the document decode now drops only the unreadable key, so other fields still load. The Scope section explains why this is a bug fix and why no issue is linked, and it mentions a possibly related issue (#26144) without claiming to fix it. The Verification section gives concrete steps, environments, before/after results, the saved file contents, the test results, and the checks that were not run (macOS, Windows, packaged installers, real older or newer settings files). The template asks for before/after screenshots for UI changes. The author includes them, but the images are hosted on an external gist link. The Verification section also ends with a model attribution line, as the template asks. Minor gaps: the conventional commit title is not shown in the provided description text, and the title is not part of the body. Those gaps are non-critical.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between b075ca2 and d388a0a.

Files selected for processing: 2

  • apps/desktop/src/settings/DesktopAppSettings.test.ts
  • apps/desktop/src/settings/DesktopAppSettings.ts

Limit details: You’ve used all 10 included reviews currently available.

@maria-rcks

maria-rcks commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

verified head a3ca0bde317205c476237d86d4ea673cf21358dc as-is on linux, using the real electron 44.10.0 desktop client, dev renderer/server, and playwright from the repository. no mocks or seeded app data.

reproduced on github/main (e925dd681904) first. both launches received this same settings document in separate task homes:

{"localEnvironmentEnabled":false,"updateChannel":"beta","wslOnly":"yes","mainWindowBounds":{"x":120,"y":80,"width":1280,"height":900}}
  • main started the local backend, showed the local environment switch on, and used default 1100×780 bounds. its next save dropped the local-off choice.
  • this head skipped the local backend, showed "This computer is off", kept the switch off, and restored 1280×900 bounds at (120,80).
  • restarted with the same file: still off. cancelling enable left it off. confirming enable started the local environment after restart.
  • created a project through the client pointing at a real git repository. codex gpt-6.1-sol, through the local proxy, completed two client-submitted turns: cat README.md returned the repository marker; a follow-up git status --short returned a clean tree. both commands exited 0 and both turns completed without errors.
  • disabled the local environment through settings and restarted again: still off, no desktop backend listener, bounds preserved. the saved document retained localEnvironmentEnabled:false and removed the unreadable fields.

the development harness requests relaunch by exiting with code 75; i relaunched the identical electron command after each restart request. session d-bus was isolated to avoid configuring the vm's keyring.

vp run check:changed 8760d063e903 passed through blacksmith-check: format, lint, knip, typechecks for both affected packages, and all 12 desktop settings tests. existing ci reports 31 successful checks. no source changes were needed.

before, main:

main incorrectly enables the local environment

after, this head with the same input:

pr preserves the disabled local environment and saved window size

local environment enable confirmation in the real desktop client

real codex follow-up turn executes git status and completes

runtime transcript

Not verified

macos, windows/wsl, native ios/android, packaged installers, tailscale exposure, remote/relay connections, and update downloads were not exercised on this linux vm. linux keyring integration was not exercised. invalid update-channel and wsl values were hand-written to reproduce the reported file corruption; project, thread, and provider data were created through the real app.

Wladefant

This comment was marked as spam.

@only21mil

only21mil commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor Author

Note

🤖 Opus 5.5 replying on behalf of Victor.

/recheck-vouch

@only21mil
only21mil marked this pull request as draft November 8, 2026 13:10
@only21mil
only21mil marked this pull request as ready for review November 8, 2026 13:10
@pingdotgg pingdotgg deleted a comment from Wladefant Nov 8, 2026
@only21mil

Copy link
Copy Markdown
Contributor Author

Note

🤖 Opus 5.5 replying on behalf of Victor.

@maria-rcks Since your verification at a3ca0bde31, the only change is b075ca2ea3, which edits only DesktopAppSettings.test.ts: the unreadable-field fixture now also sets "localEnvironmentEnabled": false and checks that it survives a later save. DesktopAppSettings.ts is unchanged, and CI passes on this head.

@only21mil

Copy link
Copy Markdown
Contributor Author

Note

🤖 Opus 5.5 replying on behalf of Victor.

I merged main 65c0195b46 because main changed DesktopAppSettings.ts since this branch's base; the merge had no conflicts and nothing else changed.

@juliusmarminge

Copy link
Copy Markdown
Member

Thanks for this. Main has the change since #36168.

Main now drops only unreadable desktop-settings.json fields while preserving valid settings, including Local environment off, across saves. I compared your complete implementation and regression-test diff with the merge: both apply Schema.catchDecoding per field and retain the existing normalization, defaults, lenient JSON parsing, and write behavior.

Closing as superseded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched Author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants