Hmbown/CodeWhale · critical

; runtime preset rollback also failed

Error message

{error:#}; runtime preset rollback also failed: {}

What it means

Compound error produced by runtime_preset_error_with_rollback: applying a runtime preset failed, the code attempted to restore previously captured runtime snapshots, and at least one restore also failed. The original error is formatted with `{error:#}` (its full anyhow chain) and appended with all rollback errors joined by "; ", so the developer sees both the primary failure and how much state may now be inconsistent.

Solutions

  1. Read the leading `{error:#}` chain first — it names why the preset apply failed; fix that (e.g. correct the preset's provider/model).
  2. Treat the runtime state as suspect: restart the TUI or reload config to rebuild clean snapshots instead of trusting the partial rollback.
  3. Validate preset values (provider exists, model supported) before applying; use a dry-run or preview if available.
  4. If restores consistently fail, the snapshot format may be stale — regenerate state from the current config files.

Example fix

// before
apply_setup_runtime_preset(app, config, preset)?; // compound rollback error
// after: validate the preset before mutating runtime state
validate_preset_against_registry(config, &preset)?;
let snapshots = capture_snapshots(app);
if let Err(err) = apply_preset(app, config, &preset) {
    for s in &snapshots { let _ = s.restore(); } // log restore errors individually
    return Err(err);
}
Defensive patterns

Strategy: validation

Validate before calling

// validate the preset against the current registry before applying
fn preset_applicable(config: &Config, preset: &Preset) -> Result<()> {
    let provider = config.provider(&preset.provider)
        .ok_or_else(|| anyhow::anyhow!("unknown provider {}", preset.provider))?;
    anyhow::ensure!(
        provider.supports_model(&preset.model),
        "provider {} does not support model {}",
        preset.provider, preset.model
    );
    Ok(())
}

Try / catch

if let Err(e) = apply_setup_runtime_preset(app, config, &preset) {
    let msg = format!("{e:#}");
    if msg.contains("rollback also failed") {
        // runtime state is inconsistent — rebuild rather than continue
        reload_runtime_from_config(app, config)?;
        return Err(anyhow::anyhow!("preset apply failed; runtime reloaded: {msg}"));
    }
    return Err(e);
}

Prevention

When it happens

Trigger: apply_setup_runtime_preset fails (invalid preset values, provider/model not available) AND snapshot.restore() on one or more captured runtime snapshots errors while rolling back — leaving the runtime in a partially modified state.

Common situations: Selecting a preset referencing a model/provider removed in a config or registry change; snapshots taken across a runtime version change so restore expects fields that no longer exist; concurrent modification of runtime state while the preset apply is in flight.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/tui/ui/provider_setup.rs:76

                }
            },
        }
    }
}

pub(crate) fn runtime_preset_error_with_rollback(
    error: anyhow::Error,
    snapshots: &[&RuntimePresetFileSnapshot],
) -> anyhow::Error {
    let rollback_errors = snapshots
        .iter()
        .filter_map(|snapshot| snapshot.restore().err())
        .map(|error| format!("{error:#}"))
        .collect::<Vec<_>>();
    if rollback_errors.is_empty() {
        error
    } else {
        anyhow::anyhow!(
            "{error:#}; runtime preset rollback also failed: {}",
            rollback_errors.join("; ")
        )
    }
}

View on GitHub (pinned to 73e0f67d83)