Hmbown/CodeWhale · error · RootPostureOutcome::Failed

could not release root config policy

Error message

could not release root config policy ({err}){rollback_note}

What it means

While changing the root config posture (e.g. granting/revoking root-config policy in settings), the commit step that releases the previous root config policy failed (`err`). The transaction then attempted to roll back the settings file with `transaction.save(&settings)`, and any secondary rollback failure is appended as `rollback_note`. The whole operation reports as RootPostureOutcome::Failed.

Solutions

  1. Read the wrapped `err` (and any rollback note) to see whether the release or the rollback failed.
  2. Close other Codewhale instances or editors holding the settings file and retry the posture change.
  3. Fix settings file permissions or free disk space as indicated by the chained errors.
  4. Inspect/repair the settings file manually if the rollback note shows it was left in a bad state.
  5. Retry the root posture operation after the environment issue is resolved.
Defensive patterns

Strategy: try-catch

Validate before calling

// before a posture change, ensure the settings file is writable and not locked
let md = std::fs::metadata(&settings_path)?;
if md.permissions().readonly() {
    anyhow::bail!("settings file read-only; posture transaction would fail");
}

Try / catch

// Rust
match apply_root_posture(transaction).await {
    RootPostureOutcome::Failed(msg) if msg.starts_with("could not release root config policy") => {
        // parse rollback note; close competing writers; repair settings; retry
    }
    other => { /* handle committed/locked outcomes */ }
}

Prevention

When it happens

Trigger: The root-posture transaction in tui/app.rs fails at the policy-release step (settings lock/apply error), and `transaction.save(&settings)` is invoked as rollback; the error surfaces whether or not the rollback itself also fails.

Common situations: The settings file is read-only or locked by another Codewhale instance; the settings file was hand-edited into a state the transaction cannot write back; disk-full during the transaction; a policy referenced in settings no longer exists.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/tui/app.rs:3600

            settings.permission_posture = Some(posture);
            if let Err(err) = transaction.save(&settings) {
                return Ok(RootPostureOutcome::Failed(format!(
                    "could not save TUI posture ({err})"
                )));
            }

            if let Err(err) = crate::config_persistence::persist_unset_root_key(
                active_config_path.as_deref(),
                "approval_policy",
            ) {
                settings.permission_posture = previous;
                let rollback_note = transaction
                    .save(&settings)
                    .err()
                    .map(|rollback| format!("; settings rollback also failed: {rollback}"))
                    .unwrap_or_default();
                return Ok(RootPostureOutcome::Failed(format!(
                    "could not release root config policy ({err}){rollback_note}"
                )));
            }
            Ok(RootPostureOutcome::Committed)
        })
        .unwrap_or_else(|err| {
            RootPostureOutcome::Failed(format!("could not lock TUI settings ({err})"))
        });
        if let RootPostureOutcome::Failed(reason) = outcome {
            return Err(reason);
        }

        self.clear_saved_approval_policy_lock();
        self.finish_approval_posture_change(next);
        Ok(())
    }

    fn next_approval_posture(&mut self, allow_root_policy: bool) -> Option<ApprovalMode> {
        if self.reject_setting_change_while_busy(MessageId::SettingSubjectPermissions) {

View on GitHub (pinned to 73e0f67d83)