Skip to content

fix(config): config mutations discard unknown JSON fields #964

Description

@PierrunoYT

Version / branch / commit

Audited on main at 903e3d13 (2026-08-23).

Problem

Most config mutators load JSON into the typed config struct and writeConfigFile rewrites the complete document with json.MarshalIndent. Fields unknown to the current binary are not represented by the struct and disappear on the next write.

Reproduction

Start with a valid config containing an additional field:

{
  "theme": "default",
  "futureSetting": {"a": 1}
}

Run a normal mutation such as SetTheme. The resulting file no longer contains futureSetting.

Expected behavior

Config writes preserve unknown fields so a current or older Zero binary does not destroy settings written by a newer version or extension.

Actual behavior

Any mutator that routes through writeConfigFile silently removes every unmodelled top-level field.

Relevant code

  • internal/config/writer.go:767-773
  • internal/config/unknownfields.go:14-22
  • internal/config/writer.go:596-621 (SetPet already uses a surgical raw-JSON update to avoid this class)

Suggested fix

Preserve extra top-level members as map[string]json.RawMessage through custom marshal/unmarshal logic, or generalize the raw-JSON mutation approach. Add a regression test proving an unknown object survives a representative config mutation.

Activity

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

    issue-approvedReviewed and approved by the core team; community PRs may implement this issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions