Hmbown/CodeWhale · warning

Config migration skipped

Error message

Config migration skipped: {err}

What it means

During startup the TUI runs the config-directory migration (codewhale_config::migrate_config_if_needed()). When it returns Err, the TUI logs "Config migration skipped: {err}" and continues with the existing config — the migration is explicitly non-fatal. The install keeps working from the old config location; nothing was moved.

Solutions

  1. Read the {err} detail in the log to find the failing file or path.
  2. Verify the source config parses (fix JSON/TOML syntax errors) and both source and destination paths are readable/writable.
  3. Manually copy the config to the new location (~/.codewhale/) and remove the old one so migration becomes a no-op.
  4. If a previous partial migration left stale state, clear the target location and retry.

Example fix

// before
~/.olddir/config.toml   (unreadable, perms 000)
// after
chmod 600 ~/.olddir/config.toml  # then relaunch to migrate
Defensive patterns

Strategy: validation

Validate before calling

let src = old_config_path(); if src.exists() { ensure_readable(&src)?; ensure_writable_dir(new_config_dir())?; }

Try / catch

match migrate_config_if_needed() { Err(err) => log::warn!("continuing with existing config: {err}"), _ => {} }

Prevention

When it happens

Trigger: migrate_config_if_needed() errors during launch (lib.rs ~11210): source config unreadable/corrupt, destination unwritable, or partial-migration state detected on a later launch.

Common situations: Upgrading from an older version that stored config elsewhere; corrupt or hand-edited config at the source path; mixed-permission installs after running the app once as root/sudo; sync tools (Dropbox) locking config files.

Understand the failure class

Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/4779496bc88ab7fa. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/lib.rs:11210

    if !cli.skip_onboarding {
        match crate::config::ensure_config_file_exists(cli.config.clone()) {
            Ok(Some(path)) => logging::info(format!(
                "Created first-run config file at {}",
                path.display()
            )),
            Ok(None) => {}
            Err(err) => logging::warn(format!("Failed to create first-run config file: {err}")),
        }
    }

    // v0.8.44: migrate config from ~/.deepseek/ to ~/.codewhale/ on first
    // launch. Non-fatal — existing installs keep working either way.
    match codewhale_config::migrate_config_if_needed() {
        Ok(Some(migration)) => {
            eprintln!("{}", migration.user_notice());
        }
        Ok(None) => {}
        Err(err) => logging::warn(format!("Config migration skipped: {err}")),
    }

    let model = config.default_model();
    let provider = config.api_provider();
    let max_subagents = cli.max_subagents.map_or_else(
        || config.max_subagents_for_provider(provider),
        |value| value.clamp(1, MAX_SUBAGENTS),
    );
    let screen_mode = startup_screen_mode(cli, config);
    let mouse_capture_preference = mouse_capture_preference(cli, config);
    let use_mouse_capture = screen_mode.mouse_capture(mouse_capture_preference);
    let use_bracketed_paste = crate::settings::Settings::load()
        .map(|s| s.effective_bracketed_paste())
        .unwrap_or_else(|_| !crate::settings::detected_legacy_windows_console_host());

    // Auto-install bundled system skills (e.g. skill-creator) on first launch.
    // Errors are non-fatal: log a warning and continue.
    let skills_dir = config.skills_dir();

View on GitHub (pinned to 433685b202)