{"record":{"id":"85da3cb8b58f69a7","repo":"tinyhumansai/openhuman","slug":"learning-forget-facet-e","errorCode":null,"errorMessage":"learning_forget_facet: {e:#}","messagePattern":"learning_forget_facet: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/agent/learning/tools.rs","lineNumber":384,"sourceCode":"            \"type\": \"object\",\n            \"properties\": { \"class\": { \"type\": \"string\" }, \"key\": { \"type\": \"string\" } },\n            \"required\": [\"class\", \"key\"]\n        })\n    }\n\n    fn permission_level(&self) -> PermissionLevel {\n        PermissionLevel::Write\n    }\n\n    async fn execute(&self, args: serde_json::Value) -> anyhow::Result<ToolResult> {\n        log::debug!(\"[tool][learning] forget_facet invoked\");\n        let class_str = read_required_str(&args, \"class\")?;\n        let key_suffix = read_required_str(&args, \"key\")?;\n        let fk = full_key(&class_str, &key_suffix);\n        let cache = get_cache()?;\n        let facet_json = match cache\n            .get(&fk)\n            .map_err(|e| anyhow::anyhow!(\"learning_forget_facet: {e:#}\"))?\n        {\n            Some(mut f) => {\n                f.user_state = UserState::Forgotten;\n                f.state = FacetState::Dropped;\n                cache\n                    .upsert(&f)\n                    .map_err(|e| anyhow::anyhow!(\"learning_forget_facet: upsert failed: {e:#}\"))?;\n                facet_to_json(&f)\n            }\n            None => serde_json::Value::Null,\n        };\n        Ok(ToolResult::success(serde_json::to_string(&json!({\n            \"facet\": facet_json,\n        }))?))\n    }\n}\n\n/// Rebuild the facet cache (heavyweight stability cycle). Default-OFF.","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/src/openhuman/agent/learning/tools.rs#L366-L402","documentation":"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.","triggerScenarios":"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.","commonSituations":"Forget racing the nightly stability rebuild; disk-full workspace; two learning tool calls executing in parallel from one agent turn.","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)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match tool_exec(\"learning_forget_facet\", args).await {\n    Err(e) if e.to_string().contains(\"learning_forget_facet:\") && !e.to_string().contains(\"upsert\") => {\n        tokio::time::sleep(Duration::from_millis(300)).await;\n        tool_exec(\"learning_forget_facet\", args).await // read-phase retry, nothing was mutated\n    }\n    other => other,\n}","preventionTips":["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"],"tags":["rust","sqlite","learning","agent-tools","forget"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}