zeroclaw-labs/zeroclaw · critical · anyhow::Error

purge_session not supported by this memory backend

Error message

purge_session not supported by this memory backend

What it means

verify_checksum_bytes (src/commands/update.rs:534) SHA-256-hashes the downloaded archive bytes and compares (case-insensitively) against the digest recorded for that asset filename in the release's SHA256SUMS. A mismatch aborts the update before anything is written to staging — the bytes received are not the bytes the release published. As the message states, the realistic causes are a corrupted transfer (truncation, proxy/AV rewriting) or actual tampering (MITM); a stale checksum file after maintainers re-uploaded an asset is a rarer third cause.

Source

Thrown at crates/zeroclaw-api/src/memory_traits.rs:328

    /// Remove the row matching `(key, agent_id)`. Siblings of the same key
    /// under other agents are untouched. Returns `true` if a row was
    /// removed. Required: no safe default exists for backends or wrappers
    /// that can hold more than one row per `key` — the unscoped `forget`
    /// would destroy sibling rows.
    async fn forget_for_agent(&self, key: &str, agent_id: &str) -> anyhow::Result<bool>;

    /// Remove all memories whose `namespace` field equals the given value.
    /// Returns the number of deleted entries.
    /// Default: returns unsupported error. Backends that support bulk deletion override this.
    async fn purge_namespace(&self, _namespace: &str) -> anyhow::Result<usize> {
        anyhow::bail!("purge_namespace not supported by this memory backend")
    }

    /// Remove all memories in a session.
    /// Returns the number of deleted entries.
    /// Default: returns unsupported error. Backends that support bulk deletion override this.
    async fn purge_session(&self, _session_id: &str) -> anyhow::Result<usize> {
        anyhow::bail!("purge_session not supported by this memory backend")
    }

    /// Remove all memories in a session for one agent.
    /// Returns the number of deleted entries.
    /// Default: returns unsupported error. Backends with per-agent storage
    /// override this; agent-scoped wrappers use it instead of composing a
    /// session list with key-only deletes.
    async fn purge_session_for_agent(
        &self,
        _session_id: &str,
        _agent_id: &str,
    ) -> anyhow::Result<usize> {
        anyhow::bail!("purge_session_for_agent not supported by this memory backend")
    }

    /// Remove every memory row attributed to the given agent alias.
    /// Returns the number of deleted entries. Called when an agent alias is
    /// removed from `[agents.<alias>]` so the database doesn't accumulate

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Re-run `zeroclaw update` — transient corruption is fixed by a fresh download
  2. If it persists, verify manually: download the archive and sha256sums from the release page and run `sha256sum -c --ignore-missing sha256sums` — a passing manual check means a middlebox is corrupting zeroclaw's in-band transfer
  3. Retry from a different, trusted network or disable AV/proxy scanning for the github release hosts
  4. If the manual check also fails, the published release is inconsistent or compromised — stay on your current version and report it to the maintainers

Example fix

# before
$ zeroclaw update
Error: checksum mismatch for 'zeroclaw-x86_64-unknown-linux-gnu.tar.gz': expected abc..., got def.... The downloaded update may be corrupted or tampered with.

# after
$ # triage: does a manual download match the published digest?
$ curl -fLO <release-url>/zeroclaw-x86_64-unknown-linux-gnu.tar.gz
$ curl -fLO <release-url>/sha256sums
$ sha256sum -c --ignore-missing sha256sums
zeroclaw-x86_64-unknown-linux-gnu.tar.gz: OK   # -> network middlebox corrupted the in-flight copy; retry from a clean network
Defensive patterns

Strategy: retry

Validate before calling

// Independent verification before trusting an update: fetch asset + sums
// once and compare digests yourself, mirroring verify_checksum_bytes.
async fn download_intact(client: &reqwest::Client, asset_url: &str, sums_url: &str) -> anyhow::Result<bool> {
    use sha2::{Digest, Sha256};
    let bytes = client.get(asset_url).send().await?.bytes().await?;
    let sums = client.get(sums_url).send().await?.text().await?;
    let name = asset_url.rsplit('/').next().unwrap_or("");
    let expected = sums
        .lines()
        .find_map(|l| {
            let (d, n) = l.split_whitespace().collect::<Vec<_>>()[..2].try_into().ok()?;
            (n.trim_start_matches('*') == name).then_some(d)
        })
        .ok_or_else(|| anyhow::anyhow!("asset missing from SHA256SUMS"))?;
    Ok(hex::encode(Sha256::digest(&bytes)).eq_ignore_ascii_case(expected))
}

Try / catch

match update::run(version, force).await {
    Err(e) if e.to_string().contains("checksum mismatch") => {
        // Retry ONCE on a fresh connection (transient corruption is common).
        // A second identical mismatch is deterministic: stop, verify
        // manually with sha256sum -c, and report possible tampering or a
        // stale SHA256SUMS — do not keep re-downloading or force-install.
    }
    other => other,
}

Prevention

When it happens

Trigger: `zeroclaw update` on a release that publishes SHA256SUMS, where the downloaded archive's SHA-256 differs from the published digest: truncated download over a flaky link, TLS-inspecting proxy or antivirus altering the byte stream, MITM attack, or the asset was re-uploaded without regenerating SHA256SUMS.

Common situations: Corporate TLS-inspection proxies that rewrite content; AV download scanning stripping or modifying bytes; unreliable networks truncating the transfer; upstream publishing pipeline replacing an asset after generating checksums.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/6cda2baa9db7b94a. Report an issue: GitHub.