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
- Retry after the concurrent writer finishes
- Distinguish from a benign miss: a truly absent key returns success with facet:null, so this error means store trouble — check the error chain
- 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
- A forget returning success with facet:null is a miss, not a failure — only Err means store trouble
- Keep forget calls away from rebuild/reset windows
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
- learning_forget_facet: upsert failed: {e:#}
- learning_update_facet: {e:#}
- learning_update_facet: upsert failed: {e:#}
- {tool}: set_user_state failed: {e:#}
- {tool}: re-read failed: {e:#}
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/85da3cb8b58f69a7.
Report an issue: GitHub.