fix(settings): distinguish unset known settings from unknown ones#9818
Conversation
`mise settings get <key>` walked the serialized current settings to find a value, but Option<T> fields that are None are skipped by TOML serialization. That made unset-but-known settings indistinguishable from typos — both returned `Unknown setting`. Check SETTINGS_META when the walk fails: if the key is known but unset, emit `Setting [<key>] is not set`; otherwise keep `Unknown setting`. Fixes #9817 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR fixes
Confidence Score: 5/5Safe to merge — only the error message path of The change is narrow: it only affects the error-handling branch in the TOML walk (no success path is modified), and No files require special attention. Important Files Changed
Reviews (3): Last reviewed commit: "test(settings): update test_settings_uns..." | Re-trigger Greptile |
There was a problem hiding this comment.
Code Review
This pull request enhances the mise settings get command to distinguish between valid but unset settings and entirely unknown settings, including new E2E tests for these cases. Feedback from the review highlights that the current check only recognizes leaf settings, causing organizational groups to still be reported as unknown. The reviewer suggested a more robust check to include these groups and recommended standardizing error message formatting by consistently using brackets for setting keys.
| } else if SETTINGS_META.contains_key(self.setting.as_str()) { | ||
| bail!("Setting [{}] is not set", self.setting); | ||
| } else { | ||
| bail!("Unknown setting: {}", self.setting); |
There was a problem hiding this comment.
The current check only identifies leaf settings as 'known'. Organizational groups (e.g., cargo, python) will still report as Unknown setting if they contain no set values, which is inconsistent with the goal of distinguishing known settings from typos.
Additionally, the error messages use different formatting styles (brackets vs. no brackets, and different phrasing). It is better to use a consistent style for both types of errors. Using brackets for the key is consistent with other error messages in the codebase.
| } else if SETTINGS_META.contains_key(self.setting.as_str()) { | |
| bail!("Setting [{}] is not set", self.setting); | |
| } else { | |
| bail!("Unknown setting: {}", self.setting); | |
| } else if SETTINGS_META.keys().any(|k| k == &self.setting || k.starts_with(&format!("{}.", self.setting))) { | |
| bail!("Setting [{}] is not set", self.setting); | |
| } else { | |
| bail!("Unknown setting: [{}]", self.setting); |
| @@ -13,6 +13,8 @@ assert_contains "mise settings -T" "all_compile = true" | |||
| mise settings unset all_compile | |||
| assert "mise settings get all_compile" "false" | |||
| assert_fail "mise settings get abcdefg" "mise ERROR Unknown setting: abcdefg" | |||
There was a problem hiding this comment.
Code Review
This pull request improves the error reporting for the settings get command by distinguishing between unknown settings and settings that are valid but currently unset. It introduces a check against SETTINGS_META to provide more specific error messages. The review feedback suggests enhancing the test suite with a case for settings that have a valid prefix but an invalid leaf name to ensure the 'Unknown setting' logic handles these scenarios correctly.
| assert_fail "mise settings get abcdefg" "mise ERROR Unknown setting: abcdefg" | ||
| assert_fail "mise settings get python.compile" "mise ERROR Setting [python.compile] is not set" | ||
| assert_fail "mise settings get cargo.registry_name" "mise ERROR Setting [cargo.registry_name] is not set" |
There was a problem hiding this comment.
To fully verify that the logic correctly distinguishes between unset known settings and actual typos (unknown settings), it is recommended to add a test case where a key has a valid prefix but an invalid leaf name (e.g., python.compyle). This ensures that the else block in src/cli/settings/get.rs is correctly reached when the full key is not present in SETTINGS_META.
assert_fail "mise settings get abcdefg" "mise ERROR Unknown setting: abcdefg"
assert_fail "mise settings get python.compyle" "mise ERROR Unknown setting: python.compyle"
assert_fail "mise settings get python.compile" "mise ERROR Setting [python.compile] is not set"
assert_fail "mise settings get cargo.registry_name" "mise ERROR Setting [cargo.registry_name] is not set"
Addresses review feedback: `mise settings get cargo` should not say "Unknown setting" if the cargo namespace happens to have no set values. Match `SETTINGS_META` keys by exact match or namespace prefix. Also add a test for a typo-with-valid-prefix (`python.compyle`) to verify it still falls through to "Unknown setting". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The test asserted the old behavior where unset-but-known settings returned "Unknown setting". Update it to match the new "Setting [<key>] is not set" message. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.5.6 x -- echo |
27.9 ± 2.0 | 22.9 | 33.4 | 1.00 |
mise x -- echo |
28.9 ± 2.3 | 23.1 | 34.9 | 1.04 ± 0.11 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.5.6 env |
27.6 ± 2.2 | 22.2 | 34.1 | 1.00 |
mise env |
28.3 ± 2.3 | 22.5 | 36.6 | 1.02 ± 0.12 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.5.6 hook-env |
28.5 ± 2.2 | 23.2 | 37.2 | 1.00 |
mise hook-env |
29.4 ± 2.4 | 23.7 | 39.3 | 1.03 ± 0.11 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.5.6 ls |
24.2 ± 1.9 | 19.7 | 28.6 | 1.00 |
mise ls |
25.2 ± 2.1 | 19.6 | 31.9 | 1.04 ± 0.12 |
xtasks/test/perf
| Command | mise-2026.5.6 | mise | Variance |
|---|---|---|---|
| install (cached) | 159ms | 159ms | +0% |
| ls (cached) | 91ms | 88ms | +3% |
| bin-paths (cached) | 89ms | 93ms | -4% |
| task-ls (cached) | 641ms | 646ms | +0% |
### 🐛 Bug Fixes - **(backend)** use runtime paths for backend bin dirs by @risu729 in [#9606](#9606) - **(ci)** preserve vendor/aqua-registry/ in PPA publish workflow by @jdx in [#9782](#9782) - **(ci)** set UTF-8 locale in e2e Docker image by @jdx in [#9820](#9820) - **(ci)** pass UTF-8 locale through to e2e tests by @jdx in [#9823](#9823) - **(conda)** dedup repodata by archive identifier instead of URL by @jdx in [#9831](#9831) - **(github)** use default shell for credential command by @risu729 in [#9664](#9664) - **(settings)** distinguish unset known settings from unknown ones by @jdx in [#9818](#9818) - **(upgrade)** remove completed progress jobs to prevent duplicate output by @jdx in [#9779](#9779) - **(vfox)** resolve GitHub token lazily inside Lua plugins by @jdx in [#9816](#9816) ### 🚜 Refactor - **(config)** separate core and backend tool options by @risu729 in [#9753](#9753) - **(schema)** reuse env directive property schemas by @risu729 in [#9651](#9651) ### 📚 Documentation - **(aliases)** fix Aliased Versions example and drop stale asdf callout by @jdx in [#9830](#9830) ### ⚡ Performance - **(aqua)** use phf for baked registry lookups by @risu729 in [#9763](#9763) - **(task)** cache per-file content hashes for source_freshness_hash_contents by @jdx in [#9819](#9819) ### 🧪 Testing - **(e2e)** pin aube to known-good version in npm package_manager test by @jdx in [#9794](#9794) ### 📦 Registry - replace unsupported exe options by @risu729 in [#9587](#9587) - update pi by @garysassano in [#9792](#9792) ### Chore - **(ci)** use non-large runners for release builds by @jdx in [#9786](#9786) - **(ci)** compare registry PRs from fork point by @risu729 in [#9643](#9643) - **(ci)** make build-copr.sh the single source of truth for COPR chroots by @jdx in [#9788](#9788) - **(ci)** use crates.io trusted publishing in release-plz by @jdx in [#9793](#9793) - **(ci)** remove autofix.ci workflow by @jdx in [#9801](#9801) - **(ci)** restore -large runner for Linux release builds by @jdx in [#9815](#9815) - **(ci)** add zizmor workflow for github actions security analysis by @jdx in [#9804](#9804) - **(ci)** assert mise run render produces no diff by @jdx in [#9803](#9803) - **(copr)** publish EL9 builds via centos-stream+epel-next-9 chroot by @jdx in [#9787](#9787) ### Ci - remove pull_request_target workflow by @jdx in [#9799](#9799) - remove caching from publishing workflows by @jdx in [#9800](#9800) ### Security - reject shell metacharacters in version strings and CI inputs by @jdx in [#9814](#9814) ## 📦 Aqua Registry Updates ### New Packages (11) - [`Code-Hex/Neo-cowsay`](https://github.com/Code-Hex/Neo-cowsay) - [`SonarSource/sonarqube-cli`](https://github.com/SonarSource/sonarqube-cli) - [`earendil-works/pi`](https://github.com/earendil-works/pi) - [`hylo-lang/hylo-new`](https://github.com/hylo-lang/hylo-new) - [`jfernandez/bpftop`](https://github.com/jfernandez/bpftop) - [`modem-dev/hunk`](https://github.com/modem-dev/hunk) - [`npm/cli`](https://github.com/npm/cli) - [`racket/racket/minimal`](https://github.com/racket/racket) - [`slackapi/slack-cli`](https://github.com/slackapi/slack-cli) - [`vectordotdev/vector`](https://github.com/vectordotdev/vector) - [`wasilibs/go-yamllint`](https://github.com/wasilibs/go-yamllint) ### Updated Packages (10) - [`DataDog/pup`](https://github.com/DataDog/pup) - [`aquasecurity/trivy`](https://github.com/aquasecurity/trivy) - [`astral-sh/uv`](https://github.com/astral-sh/uv) - [`caarlos0/svu`](https://github.com/caarlos0/svu) - [`cargo-bins/cargo-binstall`](https://github.com/cargo-bins/cargo-binstall) - [`foundry-rs/foundry`](https://github.com/foundry-rs/foundry) - [`gastownhall/beads`](https://github.com/gastownhall/beads) - [`gruntwork-io/terragrunt`](https://github.com/gruntwork-io/terragrunt) - [`pnpm/pnpm`](https://github.com/pnpm/pnpm) - [`santosr2/TerraTidy`](https://github.com/santosr2/TerraTidy)
### 🐛 Bug Fixes - **(backend)** use runtime paths for backend bin dirs by @risu729 in [jdx#9606](jdx#9606) - **(ci)** preserve vendor/aqua-registry/ in PPA publish workflow by @jdx in [jdx#9782](jdx#9782) - **(ci)** set UTF-8 locale in e2e Docker image by @jdx in [jdx#9820](jdx#9820) - **(ci)** pass UTF-8 locale through to e2e tests by @jdx in [jdx#9823](jdx#9823) - **(conda)** dedup repodata by archive identifier instead of URL by @jdx in [jdx#9831](jdx#9831) - **(github)** use default shell for credential command by @risu729 in [jdx#9664](jdx#9664) - **(settings)** distinguish unset known settings from unknown ones by @jdx in [jdx#9818](jdx#9818) - **(upgrade)** remove completed progress jobs to prevent duplicate output by @jdx in [jdx#9779](jdx#9779) - **(vfox)** resolve GitHub token lazily inside Lua plugins by @jdx in [jdx#9816](jdx#9816) ### 🚜 Refactor - **(config)** separate core and backend tool options by @risu729 in [jdx#9753](jdx#9753) - **(schema)** reuse env directive property schemas by @risu729 in [jdx#9651](jdx#9651) ### 📚 Documentation - **(aliases)** fix Aliased Versions example and drop stale asdf callout by @jdx in [jdx#9830](jdx#9830) ### ⚡ Performance - **(aqua)** use phf for baked registry lookups by @risu729 in [jdx#9763](jdx#9763) - **(task)** cache per-file content hashes for source_freshness_hash_contents by @jdx in [jdx#9819](jdx#9819) ### 🧪 Testing - **(e2e)** pin aube to known-good version in npm package_manager test by @jdx in [jdx#9794](jdx#9794) ### 📦 Registry - replace unsupported exe options by @risu729 in [jdx#9587](jdx#9587) - update pi by @garysassano in [jdx#9792](jdx#9792) ### Chore - **(ci)** use non-large runners for release builds by @jdx in [jdx#9786](jdx#9786) - **(ci)** compare registry PRs from fork point by @risu729 in [jdx#9643](jdx#9643) - **(ci)** make build-copr.sh the single source of truth for COPR chroots by @jdx in [jdx#9788](jdx#9788) - **(ci)** use crates.io trusted publishing in release-plz by @jdx in [jdx#9793](jdx#9793) - **(ci)** remove autofix.ci workflow by @jdx in [jdx#9801](jdx#9801) - **(ci)** restore -large runner for Linux release builds by @jdx in [jdx#9815](jdx#9815) - **(ci)** add zizmor workflow for github actions security analysis by @jdx in [jdx#9804](jdx#9804) - **(ci)** assert mise run render produces no diff by @jdx in [jdx#9803](jdx#9803) - **(copr)** publish EL9 builds via centos-stream+epel-next-9 chroot by @jdx in [jdx#9787](jdx#9787) ### Ci - remove pull_request_target workflow by @jdx in [jdx#9799](jdx#9799) - remove caching from publishing workflows by @jdx in [jdx#9800](jdx#9800) ### Security - reject shell metacharacters in version strings and CI inputs by @jdx in [jdx#9814](jdx#9814) ## 📦 Aqua Registry Updates ### New Packages (11) - [`Code-Hex/Neo-cowsay`](https://github.com/Code-Hex/Neo-cowsay) - [`SonarSource/sonarqube-cli`](https://github.com/SonarSource/sonarqube-cli) - [`earendil-works/pi`](https://github.com/earendil-works/pi) - [`hylo-lang/hylo-new`](https://github.com/hylo-lang/hylo-new) - [`jfernandez/bpftop`](https://github.com/jfernandez/bpftop) - [`modem-dev/hunk`](https://github.com/modem-dev/hunk) - [`npm/cli`](https://github.com/npm/cli) - [`racket/racket/minimal`](https://github.com/racket/racket) - [`slackapi/slack-cli`](https://github.com/slackapi/slack-cli) - [`vectordotdev/vector`](https://github.com/vectordotdev/vector) - [`wasilibs/go-yamllint`](https://github.com/wasilibs/go-yamllint) ### Updated Packages (10) - [`DataDog/pup`](https://github.com/DataDog/pup) - [`aquasecurity/trivy`](https://github.com/aquasecurity/trivy) - [`astral-sh/uv`](https://github.com/astral-sh/uv) - [`caarlos0/svu`](https://github.com/caarlos0/svu) - [`cargo-bins/cargo-binstall`](https://github.com/cargo-bins/cargo-binstall) - [`foundry-rs/foundry`](https://github.com/foundry-rs/foundry) - [`gastownhall/beads`](https://github.com/gastownhall/beads) - [`gruntwork-io/terragrunt`](https://github.com/gruntwork-io/terragrunt) - [`pnpm/pnpm`](https://github.com/pnpm/pnpm) - [`santosr2/TerraTidy`](https://github.com/santosr2/TerraTidy)
Summary
mise settings get <key>walked the serialized current settings to look up a value, butOption<T>fields that areNoneare skipped by TOML serialization. That made unset-but-known settings indistinguishable from typos — both returnedUnknown setting.SETTINGS_METAfor the full key. If known, emitSetting [<key>] is not set; otherwise keepUnknown setting.Reported in #9817.
Before
After
Test plan
mise settings get python.compile→Setting [python.compile] is not set(exit 1)mise settings get cargo.registry_name→Setting [cargo.registry_name] is not set(exit 1)mise settings get abcdefg→Unknown setting: abcdefg(unchanged)mise settings get legacy_version_file→true(unchanged)mise settings get python(parent key) → inline table (unchanged)cli/test_settings_setextended and passing🤖 Generated with Claude Code
Note
Low Risk
Low risk: small change to
mise settings geterror handling plus updated e2e expectations; main impact is different user-facing error text for missing known keys.Overview
mise settings getnow distinguishes between a known setting that is currently unset vs a truly unknown key by consultingSETTINGS_METAwhen a lookup fails.E2E CLI tests are updated/extended to assert the new
Setting [<key>] is not seterror for known-but-unset keys (including dotted keys), while keepingUnknown settingfor typos.Reviewed by Cursor Bugbot for commit 5186233. Bugbot is set up for automated code reviews on this repo. Configure here.