Skip to content

Repair an outdated settings.yaml on load instead of crashing Core - #419

Merged
Shackless merged 2 commits into
developfrom
fix/settings-boot-repair
Sep 20, 2026
Merged

Shackless merged 2 commits into
developfrom
fix/settings-boot-repair

Conversation

@Shackless

Copy link
Copy Markdown
Contributor

The crash

A tester's 3.2.2 install ended every start with:

Invalid config 'C:\Users\...\3_2_2\configs\settings.yaml':
1 validation error for SettingsConfig
stt  Field required
...
pydantic_core._pydantic_core.ValidationError: 9 validation errors for SettingsConfig
stt  Field required [type=missing, input_value={}, input_type=dict]

Two errors, one call. load_settings_config reported the file as invalid, then
fell back to SettingsConfig() — which is not constructible, because no field
in SettingsConfig has a default. The exception came out of ConfigManager's
constructor, so Core died in main.py:97. The migration that would have
repaired the file runs in main.py:559 and never got there; every following
start hit the same wall.

Why his settings.yaml was out of date

b3eb4b4f bumped LOCAL_VERSION to 3.2.2 on 2026-09-15. 948ba0ca (#417)
added the required stt block to settings.yaml a day later. An unstable dev
build from between those two commits writes 3_2_2/configs/settings.yaml
without stt and a completed .migration marker beside it — so the
3.2.1 → 3.2.2 migration, which does write stt correctly, never runs for that
install again.

Checked the other two: defaults.yaml and mcp.template.yaml from that same
commit still validate against the current models (condense_keep_recent_tokens
and disabled_tools both have defaults). settings.yaml is the only one that
breaks.

What changed

  • load_settings_config validates the file as before. If that fails, it fills
    the missing keys from templates/configs/settings.yaml (deep merge, user
    values always win), writes the repaired file back and says so in the log.
  • A file that fails on a value instead of a missing key is left on disk
    untouched — nobody can guess what the user meant — and Core comes up on the
    shipped defaults so Settings is there to correct it in.
  • A settings.yaml that already validates is not rewritten.
  • create_settings_config writes the template instead of an empty file. An
    empty file has no value for any required field, i.e. the same crash.
  • In the migration: a settings/defaults step that fails validation now persists
    what it migrated. It used to leave the previous version's file in the new
    version's folder while perform_migration wrote the .migration marker,
    freezing that state for good.
  • _deep_merge_over in the migration service now calls the shared
    deep_merge_configs.

Tests

tests/test_settings_repair.py (local only, tests/ is gitignored): a 3.2.1
settings.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.

…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.
@Shackless
Shackless merged commit 45a6c5e into develop Sep 20, 2026
2 checks passed
@Shackless
Shackless deleted the fix/settings-boot-repair branch September 20, 2026 07:33
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