zeroclaw-labs/zeroclaw · error

memory write blocked by content scan: {kinds}

Error message

memory write blocked by content scan: {kinds}

What it means

process_content() runs threat::scan over the (post-redaction) content whenever threat_scan is on or strict. If findings exist and threat_scan_on_hit = reject, the write is aborted before reaching the backend, and the error lists the finding kinds. This is the policy working as designed (fail-closed); a WARN 'memory write flagged by content scan' is logged first.

Source

Thrown at crates/zeroclaw-memory/src/scanned.rs:212

            if !findings.is_empty() {
                let kinds = findings
                    .iter()
                    .map(|finding| finding.kind.to_string())
                    .collect::<Vec<_>>()
                    .join(",");
                ::zeroclaw_log::record!(
                    WARN,
                    ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)
                        .with_outcome(::zeroclaw_log::EventOutcome::Failure)
                        .with_attrs(::serde_json::json!({
                                "key": key,
                                "namespace": namespace,
                                "kinds": kinds,
                        })),
                    "memory write flagged by content scan"
                );
                if matches!(on_hit, OnHit::Reject) {
                    anyhow::bail!("memory write blocked by content scan: {kinds}");
                }
            }
        }

        Ok(persisted)
    }

    /// Validate namespace/category policy for a write. Any violation
    /// aborts the write.
    async fn enforce_policy(
        &self,
        key: &str,
        namespace: Option<&str>,
        category: &MemoryCategory,
    ) -> anyhow::Result<()> {
        let namespace = namespace.unwrap_or("default");
        let enforcer = PolicyEnforcer::new(&self.policy);
        if let Err(error) =

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. If the content is legitimately unsafe to persist, treat the error as final: log and drop the write — that is the policy doing its job
  2. Switch threat_scan_on_hit to block-on-read to persist flagged rows but withhold them at recall
  3. Pre-clean the content (strip or rewrite flagged passages) before store
  4. Move from strict to on if strict-scope patterns are too aggressive, and report false positives

Example fix

# before
[memory.policy]
threat_scan = "strict"
threat_scan_on_hit = "reject"

# after
[memory.policy]
threat_scan = "strict"
threat_scan_on_hit = "block-on-read"   # writes persist; flagged rows withheld at recall
Defensive patterns

Strategy: try-catch

Validate before calling

// Optional pre-flight if you expose the threat module: scan before storing
// let findings = zeroclaw_memory::threat::scan(&content, Scope::Strict);
// if !findings.is_empty() { /* sanitize or route to a side log instead of store() */ }

Type guard

fn is_scan_rejected(e: &anyhow::Error) -> bool {
    e.to_string().starts_with("memory write blocked by content scan")
}

Try / catch

match memory.store(key, content).await {
    Err(e) if is_scan_rejected(&e) => { log_rejected(key, &e); Ok(()) } // policy win: drop write, keep agent alive
    other => other,
}

Prevention

When it happens

Trigger: Storing content containing patterns the scanner flags (e.g., prompt-injection markers under strict scope) while [memory.policy] has threat_scan = on|strict and threat_scan_on_hit = "reject".

Common situations: Agents persisting scraped web pages, raw model output, or user text containing injection-style phrasing; strict mode flagging innocuous content; CI tests storing fixture text that trips the scanner.

Related errors


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