Skip to content

[Bug]: Settings saves revert external edits to settings.json #18571

Open

Description

@f4llenz

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Run t3 serve and connect a client.
  2. Make the client save settings faster than every 100 ms, or save once within 100 ms after the next step.
  3. Replace settings.json from outside T3 Code, for example with a script that adds a customModels entry and renames the new file into place.
  4. Read settings.json again.

Expected behavior

The save applies its patch to the file on disk. The external edit stays.

Actual behavior

The save writes the server's cached settings back, and the external edit is gone.

Cause:

  • updateAndPersistSettings (apps/server/src/serverSettings.ts) applies the patch to the cached settings and writes the whole result.
  • The cache refreshes only through the file watcher, debounced to 100 ms of quiet (Stream.debounce).
  • Every save also triggers a watcher event. Saves that arrive less than 100 ms apart keep the debounce from firing, so the cache never reloads and every save writes the old file back.

We hit this with saves 20 to 40 ms apart from the client loop in #18572. A fleet script's edit to settings.json was reverted about 20 seconds after it landed.

A related case: once the watcher has loaded a settings.json that does not parse, the cache holds defaults. The next save then writes defaults plus the patch over the user's file, although the loader says such a file "must stay on disk for the user to repair".

Impact

Major degradation or frequent failure

Version or commit

0.0.46-nightly.20261010.2935 (98beed1). Same code on origin/main f498b35.

Environment

t3 serve on macOS and Linux.

Workaround

After an external edit, wait until settings.json has stopped changing, then read it back and apply the edit again if it was reverted.

Activity

  1. juliusmarminge commented on Oct 12, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Confirmed on main. This is a bug, not intended behavior. The server watches settings.json so that external edits are picked up, and the loader says outright that a file it can't parse "must stay on disk for the user to repair". Saves currently break both of those.

    What main does (apps/server/src/serverSettings.ts):

    • updateAndPersistSettings applies the patch to the cached settings (getSettingsFromCache) and writes the whole result back with writeSettingsAtomically. It never re-reads the file.
    • The cache is only invalidated by the watcher, which goes through Stream.debounce(100ms). Each save fires another watcher event, so saves less than 100 ms apart keep resetting the debounce. The cache never reloads, and every save writes the stale snapshot over the external edit.
    • If the file doesn't parse, the cache holds defaults (settingsFileTrusted = false). The next save then writes defaults plus the patch over the user's broken file, which contradicts that loader comment.

    The trigger you hit, saves 20 to 40 ms apart, comes from #18572. That one is tracked separately, but any burst of saves can cause this. Until it's fixed, the workaround is to make external edits while no client is saving, then read the file back to check.

  2. added
    acceptedfeature request accepted
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedfeature request acceptedbugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions