Repair an outdated settings.yaml on load instead of crashing Core - #419
Merged
Merged
Conversation
…Core b3eb4b4 bumped the version to 3.2.2 on 2026-09-15; 948ba0c added the required 'stt' block to settings.yaml a day later. A tester who installed an unstable dev build in between has a 3_2_2/configs/settings.yaml without 'stt' and a completed .migration marker next to it, so no migration ever touches it again. ConfigManager validates that file before the migration runs, and its fallback, SettingsConfig(), is not constructible either - every field is required. Core died in ConfigManager's constructor on every start. load_settings_config now fills the missing keys from the shipped template, keeps every user value and writes the repaired file back. A file that fails on a value instead of a missing key is left on disk untouched and Core comes up on the defaults. A settings.yaml that already validates is not rewritten. create_settings_config writes the template instead of an empty file, and a settings/defaults migration step that fails validation now persists what it migrated instead of leaving the previous version's file in the new folder.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The crash
A tester's 3.2.2 install ended every start with:
Two errors, one call.
load_settings_configreported the file as invalid, thenfell back to
SettingsConfig()— which is not constructible, because no fieldin
SettingsConfighas a default. The exception came out ofConfigManager'sconstructor, so Core died in
main.py:97. The migration that would haverepaired the file runs in
main.py:559and never got there; every followingstart hit the same wall.
Why his settings.yaml was out of date
b3eb4b4fbumpedLOCAL_VERSIONto 3.2.2 on 2026-09-15.948ba0ca(#417)added the required
sttblock tosettings.yamla day later. An unstable devbuild from between those two commits writes
3_2_2/configs/settings.yamlwithout
sttand a completed.migrationmarker beside it — so the3.2.1 → 3.2.2 migration, which does write
sttcorrectly, never runs for thatinstall again.
Checked the other two:
defaults.yamlandmcp.template.yamlfrom that samecommit still validate against the current models (
condense_keep_recent_tokensand
disabled_toolsboth have defaults).settings.yamlis the only one thatbreaks.
What changed
load_settings_configvalidates the file as before. If that fails, it fillsthe missing keys from
templates/configs/settings.yaml(deep merge, uservalues always win), writes the repaired file back and says so in the log.
untouched — nobody can guess what the user meant — and Core comes up on the
shipped defaults so Settings is there to correct it in.
settings.yamlthat already validates is not rewritten.create_settings_configwrites the template instead of an empty file. Anempty file has no value for any required field, i.e. the same crash.
what it migrated. It used to leave the previous version's file in the new
version's folder while
perform_migrationwrote the.migrationmarker,freezing that state for good.
_deep_merge_overin the migration service now calls the shareddeep_merge_configs.Tests
tests/test_settings_repair.py(local only,tests/is gitignored): a 3.2.1settings.yaml boots and keeps the user's values, an empty file boots on the
template, a bad value boots on defaults and leaves the file alone, a current
file is not rewritten. The 98 tests in the config/migration area pass.