tinyhumansai/openhuman · warning
{tool}: facet not found: {fk}
Error message
{tool}: facet not found: {fk} What it means
Thrown by set_pin (learning_pin_facet / learning_unpin_facet) when set_user_state returned Ok(false) — the UPDATE on user_profile matched zero rows, so no facet exists with the composed full key '{class}/{key}'. This is a semantic not-found, not a storage failure: the class prefix or key suffix does not match any row, or the facet was evicted/deleted earlier.
Source
Thrown at src/openhuman/agent/learning/tools.rs:275
}))?))
}
}
/// Set/clear a facet's pin via `set_user_state`. Shared by pin/unpin.
async fn set_pin(
args: serde_json::Value,
tool: &str,
state: UserState,
) -> anyhow::Result<ToolResult> {
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 updated = cache
.set_user_state(&fk, state)
.map_err(|e| anyhow::anyhow!("{tool}: set_user_state failed: {e:#}"))?;
if !updated {
return Err(anyhow::anyhow!("{tool}: facet not found: {fk}"));
}
let facet = cache
.get(&fk)
.map_err(|e| anyhow::anyhow!("{tool}: re-read failed: {e:#}"))?;
Ok(ToolResult::success(serde_json::to_string(&json!({
"facet": facet.as_ref().map(facet_to_json),
}))?))
}
/// Pin a facet. Default-OFF.
pub struct LearningPinFacetTool;
#[async_trait]
impl Tool for LearningPinFacetTool {
fn name(&self) -> &str {
"learning_pin_facet"
}
View on GitHub (pinned to a221052e0d)
Solutions
- Call learning_list_facets (optionally filtered by class) and pin using a key verbatim from the result
- If the list is empty or the facet is missing, re-derive it via learning_rebuild_cache or normal conversation before pinning
- Check exact spelling and the class prefix — keys are 'class/suffix' strings and the class must match FacetClass vocabulary
Example fix
// before: guessed key
tool: learning_pin_facet {"class":"style","key":"tone"} // -> facet not found: style/tone
// after: list first, use verbatim key
tool: learning_list_facets {"class":"style"} // returns key "style/verbosity"
tool: learning_pin_facet {"class":"style","key":"verbosity"} Defensive patterns
Strategy: validation
Validate before calling
// Resolve the real key from the cache before pinning:
let facets = tool_exec("learning_list_facets", json!({"class": class})).await?; // returns keys like "style/verbosity"
let suffix = facets.iter().find(|f| f.key == format!("{class}/{key}"))
.ok_or_else(|| anyhow::"facet {class}/{key} not in cache — re-derive it first")?;
tool_exec("learning_pin_facet", json!({"class": class, "key": key})).await Type guard
fn known_facet_key(listed: &[String], class: &str, key: &str) -> bool {
listed.iter().any(|k| k == &format!("{class}/{key}"))
} Try / catch
match tool_exec("learning_pin_facet", args).await {
Err(e) if e.to_string().contains("facet not found") => {
let listed = tool_exec("learning_list_facets", json!({})).await?; // refresh, pick verbatim key
/* re-issue with a key from `listed` or surface to the user */
unimplemented!()
}
other => other,
} Prevention
- Always source facet keys from learning_list_facets output, never from the model's memory
- Treat an empty facet list after learning_reset_cache as expected — re-derive facets before pinning
- Remember keys are 'class/suffix' strings; the class must be valid FacetClass vocabulary
When it happens
Trigger: Pinning/unpinning with a class/key pair the agent invented instead of one returned by learning_list_facets; the facet was evicted by a stability rebuild (drop_below_threshold) or removed by learning_reset_cache (non-pinned facets are deleted) between listing and pinning; whitespace/format drift in the key suffix.
Common situations: LLM hallucinating plausible facet keys like 'style/tone' when the cache holds 'style/verbosity'; acting on a stale facet list from earlier in a long session; pinning after the user reset the cache.
Related errors
- artifact_get: {e}
- artifact_delete: {e}
- learning_update_facet: {e:#}
- learning_update_facet: upsert failed: {e:#}
- {tool}: set_user_state failed: {e:#}
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/e7ae3770c064d96d.
Report an issue: GitHub.