Hmbown/CodeWhale · error · anyhow::Error

skill content changed since audit (expected {expected}, foun

Error message

skill content changed since audit (expected {expected}, found {current}); re-review before mutating

What it means

verify_expected_digest recomputes the package digest and compares it to the digest recorded at audit time (or supplied by the caller). This bail fires on mismatch: the skill's files changed on disk after the user reviewed them, so proceeding could execute unreviewed content. The modified skill package is the input at fault; this is a TOCTOU/consistency guard used by import, update, remove, and trust.

Source

Thrown at crates/tui/src/skills/mutation.rs:561

        _ => None,
    }
    .filter(|name| !name.is_empty())
    .ok_or_else(|| {
        anyhow::anyhow!(
            "invalid on-disk package directory for skill '{}'",
            skill_id.canonical_name
        )
    })?;
    Ok(name)
}

fn verify_expected_digest(path: &Path, expected: Option<&str>) -> Result<Option<String>> {
    let current = package_digest::compute_package_digest(path)
        .with_context(|| format!("cannot digest {}", path.display()))?;
    if let Some(expected) = expected
        && expected != current
    {
        bail!(
            "skill content changed since audit (expected {expected}, found {current}); \
             re-review before mutating"
        );
    }
    Ok(Some(current))
}

fn ensure_remote_updatable(skill_dir: &Path) -> Result<()> {
    let marker_path = skill_dir.join(install::INSTALLED_FROM_MARKER);
    let body = fs::read_to_string(&marker_path)
        .with_context(|| format!("failed to read {}", marker_path.display()))?;
    let value: serde_json::Value = serde_json::from_str(&body)
        .with_context(|| format!("malformed {}", install::INSTALLED_FROM_MARKER))?;
    let spec = value
        .get("spec")
        .and_then(|v| v.as_str())
        .unwrap_or_default();
    if !install::is_registry_updatable_spec(spec) {

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Re-review the skill contents (the review gate) and retry the mutation with the fresh digest
  2. Restore the package to its audited state before mutating
  3. Re-run the skills scan to pick up the new digest as the audit baseline
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at crates/tui/src/skills/mutation.rs:561 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/95be4c86e86d16b4. Report an issue: GitHub.