tinyhumansai/openhuman · error

learning_forget_facet: {e:#}

Error message

learning_forget_facet: {e:#}

What it means

Thrown by learning_forget_facet when the initial FacetCache::get() for '{class}/{key}' fails at the storage layer. Like the update tool's get error, this precedes any state change — nothing was modified. The forget tool tolerates a missing facet (Some/None match, None returns facet: null success), so this error specifically means the lookup query itself errored.

Source

Thrown at src/openhuman/agent/learning/tools.rs:384

            "type": "object",
            "properties": { "class": { "type": "string" }, "key": { "type": "string" } },
            "required": ["class", "key"]
        })
    }

    fn permission_level(&self) -> PermissionLevel {
        PermissionLevel::Write
    }

    async fn execute(&self, args: serde_json::Value) -> anyhow::Result<ToolResult> {
        log::debug!("[tool][learning] forget_facet invoked");
        let class_str = read_required_str(&args, "class")?;
        let key_suffix = read_required_str(&args, "key")?;
        let fk = full_key(&class_str, &key_suffix);
        let cache = get_cache()?;
        let facet_json = match cache
            .get(&fk)
            .map_err(|e| anyhow::anyhow!("learning_forget_facet: {e:#}"))?
        {
            Some(mut f) => {
                f.user_state = UserState::Forgotten;
                f.state = FacetState::Dropped;
                cache
                    .upsert(&f)
                    .map_err(|e| anyhow::anyhow!("learning_forget_facet: upsert failed: {e:#}"))?;
                facet_to_json(&f)
            }
            None => serde_json::Value::Null,
        };
        Ok(ToolResult::success(serde_json::to_string(&json!({
            "facet": facet_json,
        }))?))
    }
}

/// Rebuild the facet cache (heavyweight stability cycle). Default-OFF.

View on GitHub (pinned to a221052e0d)

Solutions

  1. Retry after the concurrent writer finishes
  2. Distinguish from a benign miss: a truly absent key returns success with facet:null, so this error means store trouble — check the error chain
  3. Verify store health with learning_cache_stats (a read-only aggregate over the same table)
Defensive patterns

Strategy: retry

Try / catch

match tool_exec("learning_forget_facet", args).await {
    Err(e) if e.to_string().contains("learning_forget_facet:") && !e.to_string().contains("upsert") => {
        tokio::time::sleep(Duration::from_millis(300)).await;
        tool_exec("learning_forget_facet", args).await // read-phase retry, nothing was mutated
    }
    other => other,
}

Prevention

When it happens

Trigger: Forgetting a facet while the SQLite DB is locked by a rebuild/reset writer; corrupted user_profile table; workspace DB removed or unreadable at that moment.

Common situations: Forget racing the nightly stability rebuild; disk-full workspace; two learning tool calls executing in parallel from one agent turn.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/85da3cb8b58f69a7. Report an issue: GitHub.