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
- Read the {err} detail in the log to find the failing file or path.
- Verify the source config parses (fix JSON/TOML syntax errors) and both source and destination paths are readable/writable.
- Manually copy the config to the new location (~/.codewhale/) and remove the old one so migration becomes a no-op.
- 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
- Validate the old config file parses before upgrading versions.
- Keep both old and new config directories user-owned and writable.
- Avoid placing config in sync-tool directories that can lock files.
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
- Failed to create first-run config file
- Antigravity is a retired, non-runnable legacy provider…
- Antigravity is a retired, non-runnable legacy provider…
- Choose a model for the destination provider before…
- Codewhale credentials directory cannot be a volume root
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)