Skip to content

Add lenient_config to ignore unknown config fields instead of failing - #73

Open
HoneyHazard wants to merge 1 commit into
tsowell:mainfrom
HoneyHazard:lenient-config
Open

Add lenient_config to ignore unknown config fields instead of failing#73
HoneyHazard wants to merge 1 commit into
tsowell:mainfrom
HoneyHazard:lenient-config

Conversation

@HoneyHazard

Copy link
Copy Markdown

⚠️ Full Disclosure: Drafted with AI assistance (Claude); reviewed by me briefly. I am neither a RUST developer nor pipewire expert. If I should stop making these PRs into your wonderful project, please let me know. ⚠️

That being said, I hope these can be helpful and useful additions that users could appreciate.


Every config struct currently uses #[serde(deny_unknown_fields)], so any unrecognized field anywhere in wiremix.toml - a typo, or a key from a different wiremix version than the config was written for - makes wiremix refuse to start at all, with no way to opt out. This came up concretely on my own machine: I keep a couple of not-yet-upstream fork-only theme keys (row_selected, row_unselected) in my config, and anything invoking stock /usr/bin/wiremix directly (bypassing PATH) would fail outright rather than just not styling those rows.

This adds a lenient_config config option (default false, so today's strict-by-default behavior is unchanged) with matching --lenient-config/--no-lenient-config CLI flags, following the same pattern as mouse/--mouse/--no-mouse and friends. When enabled, unknown fields are logged as warnings and ignored instead of erroring:

$ wiremix --lenient-config
wiremix: warning: ignoring unknown configuration field 'totally_unknown_field'
  • Uses the serde_ignored crate to collect every ignored field's path across the whole file in one pass - not just the first one hit - regardless of nesting depth (themes.default.foo, [[keybindings]] entries, etc.), so both the default strict error and --lenient-config's warnings report everything at once rather than one-at-a-time-per-run.
  • Required removing #[serde(deny_unknown_fields)] from the individual structs (ConfigFile, Keybinding, Names, Filter, ThemeOverlay, StyleDef, CharSetOverlay, and the raw struct behind NameOverride's custom Deserialize impl) - serde_ignored's callback only fires for fields a struct's own Deserialize impl would otherwise silently drop, and deny_unknown_fields makes that struct hard error before serde_ignored ever gets a chance to see it, bypassing the lenient/strict decision entirely.
  • The one exception is the test-only strict::ConfigFile used to validate that the shipped example wiremix.toml documents every field exhaustively - that one keeps deny_unknown_fields, since catching drift there is its whole purpose and has nothing to do with runtime behavior.

Tested:

  • cargo test --release: 147/147 passing (includes new tests for: unknown fields at the top level, inside [[keybindings]], [names]/[[names.overrides]], [themes.*], and [char_sets.*] all still erroring by default; lenient_config = true in the file and --lenient-config on the CLI both suppressing the error; --no-lenient-config overriding a lenient_config = true set in the file back to strict)
  • cargo fmt --check / cargo clippy --release --all-targets -- -D warnings / cargo doc --no-deps (matching this repo's CI): all clean
  • Live-verified with a real config file containing an unrecognized field: fails to start with a clear error by default; starts normally and prints a warning to stderr with --lenient-config; a lenient_config = true line in the config file has the same effect, and --no-lenient-config on the command line correctly overrides that back to strict

Every config struct currently uses #[serde(deny_unknown_fields)], so any
unrecognized field anywhere in wiremix.toml - a typo, or a key from a
newer/older wiremix version, including this fork's own not-yet-upstream
keys - makes wiremix refuse to start at all, with no way to opt out.

Adds a lenient_config config option (default false) with matching
--lenient-config/--no-lenient-config CLI flags. When enabled, unknown
fields are logged as warnings and ignored instead of erroring, using
serde_ignored to collect every ignored field path across the whole file
in one pass (not just the first one hit) regardless of nesting depth, so
--lenient-config's warning output and the default strict error message
both report everything at once.

Requires removing #[serde(deny_unknown_fields)] from the individual
structs, since serde_ignored's callback only fires for fields a struct's
own Deserialize impl would otherwise silently drop - deny_unknown_fields
makes that struct error out before serde_ignored ever sees it, bypassing
the lenient/strict decision entirely. The one exception is the
test-only strict::ConfigFile used to validate the shipped example
wiremix.toml stays exhaustive - that one keeps deny_unknown_fields
since catching drift there is its whole purpose.
@HoneyHazard
HoneyHazard marked this pull request as ready for review August 10, 2026 05:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant