Hmbown/CodeWhale · error

settings.toml: invalid TOML

Error message

settings.toml: invalid TOML

What it means

This load path (used by migration) reads settings.toml and, because migration must not commit fallback defaults as if the archived selections were actually read, it hard-fails via ensure! when the parsed settings carry a load_error — i.e. the TOML on disk failed to parse. Interactive loads may fall back to defaults, but this stricter path refuses so corrupt settings are never silently persisted.

Solutions

  1. Validate the file with a TOML parser (e.g. `python -c "import tomllib; tomllib.load(open('settings.toml','rb'))"`) and fix the reported syntax error
  2. Restore settings.toml from a backup or delete it so defaults regenerate, then re-enter settings
  3. Re-save the file from the app's /config editor once it parses cleanly

Example fix

// before: settings.toml has a syntax error
// model = "deepseek-chat
//   (missing closing quote)
// after: fixed TOML
// model = "deepseek-chat"
let settings = Settings::load_for_migration()?; // Ok once TOML parses
Defensive patterns

Strategy: try-catch

Validate before calling

fn toml_parses(p: &Path) -> bool {
    std::fs::read_to_string(p).map(|s| s.parse::<toml::Value>().is_ok()).unwrap_or(false)
}

Try / catch

match Settings::load_for_migration() {
    Ok(s) => s,
    Err(e) => { eprintln!("fix settings.toml before migrating: {e}"); return; }
}

Prevention

When it happens

Trigger: Migrating or programmatically loading a settings.toml that contains syntax errors (unclosed bracket, bad escape, trailing comma in a table, wrong type for a field) such that the TOML parser sets load_error.

Common situations: User hand-edited settings.toml and introduced a TOML syntax error; an editor or script wrote non-TOML content; a partially written/corrupted file after a crash or disk-full during save.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/457e3f3722bbe5af. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/settings.rs:784

        settings.apply_env_overrides();
        Ok(settings)
    }

    /// Read archived route preferences from the user-global settings store.
    ///
    /// Canonical config migration must not inherit a project config's sibling
    /// settings or runtime environment overlays, and must not migrate files.
    pub(crate) fn load_legacy_route_preferences_read_only() -> Result<Self> {
        let (primary, legacy_home, legacy_config_dir) = settings_path_candidates_for_scope(false);
        let settings = Self::load_persisted_from_candidates_with_migration(
            primary,
            legacy_home,
            legacy_config_dir,
            false,
        )?;
        // Interactive readers may recover with defaults, but migration must
        // not commit those defaults as if the archived selection were read.
        anyhow::ensure!(settings.load_error.is_none(), "settings.toml: invalid TOML");
        Ok(settings)
    }

    /// Load the normalized values stored on disk without terminal/runtime
    /// overlays. Configuration editors use this path so a value labelled
    /// "saved" never silently reports a tmux, SSH, or accessibility override.
    pub(crate) fn load_persisted() -> Result<Self> {
        with_settings_transaction(SettingsTransaction::load)
    }

    /// Load persisted values while the caller already holds the settings
    /// process mutex and adjacent file lock.
    fn load_persisted_locked() -> Result<Self> {
        let (primary, legacy_home, legacy_config_dir) = settings_path_candidates();
        Self::load_persisted_from_candidates(primary, legacy_home, legacy_config_dir)
    }

    /// Load normalized disk values for a diagnostic without creating a

View on GitHub (pinned to 73e0f67d83)