{"record":{"id":"06fdf8cb6023dcd8","repo":"zeroclaw-labs/zeroclaw","slug":"unknown-other","errorCode":null,"errorMessage":"unknown {}: {other}","messagePattern":"unknown (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-memory/src/knowledge_graph.rs","lineNumber":46,"sourceCode":"\n        impl $name {\n            pub const ALL: &'static [Self] = &[$(Self::$variant),+];\n            pub const SCHEMA_VALUES: &'static [&'static str] = &[$($value),+];\n\n            pub fn as_str(&self) -> &'static str {\n                match self {\n                    $(Self::$variant => $value),+\n                }\n            }\n\n            pub fn schema_values() -> &'static [&'static str] {\n                Self::SCHEMA_VALUES\n            }\n\n            pub fn parse(s: &str) -> anyhow::Result<Self> {\n                match s {\n                    $($value => Ok(Self::$variant),)+\n                    other => anyhow::bail!(\n                        \"unknown {}: {other}\",\n                        $error_label\n                    ),\n                }\n            }\n        }\n    };\n}\n\nknowledge_enum! {\n    /// The kind of knowledge captured in a node.\n    pub enum NodeType {\n        Pattern => \"pattern\",\n        Decision => \"decision\",\n        Lesson => \"lesson\",\n        Expert => \"expert\",\n        Technology => \"technology\",\n        Client => \"client\",","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-memory/src/knowledge_graph.rs#L28-L64","documentation":"knowledge_graph.rs defines its enums (NodeType, Relation) with the knowledge_enum! macro, whose generated parse(s) accepts only the exact snake_case schema strings and bails with \"unknown <label>: <value>\" otherwise — the label is \"node type\" for NodeType and \"relation\" for Relation. Valid values: node types pattern|decision|lesson|expert|technology|client|contact|interaction; relations uses|replaces|extends|authored_by|applies_to|manages_client|contact_of|interacted_with. Because nodes and edges store these strings in SQLite columns and parse them back on read, a bad string in the DB or in caller/user input produces this error at parse time.","triggerScenarios":"NodeType::parse or Relation::parse receiving anything outside the fixed set: \"authored-by\" or \"authored by\" instead of \"authored_by\", camelCase like \"AuthoredBy\", uppercase or whitespace-padded values, or a value from a user command routed through the graph's capture/relate handlers. Also triggered when a database row contains a node_type/relation written by a different (newer or older) ZeroClaw version whose vocabulary has drifted.","commonSituations":"Passing free-form user input straight to parse; scripts migrating a graph between versions; enum variants added or renamed between releases while the SQLite file persists old strings; JSON configs that cased the value differently than the serde snake_case mapping.","solutions":["Pass one of the exact snake_case schema strings; use NodeType::SCHEMA_VALUES / Relation::SCHEMA_VALUES (or as_str on a known variant) instead of hand-typing the literal.","Normalize input before parsing: trim, lowercase, and convert '-' or spaces to '_' for relation names.","If the value came from a stored row, inspect the nodes/edges tables for the offending string and migrate or fix those rows to the current vocabulary.","Pin your ZeroClaw version when moving graph databases between installs so enum vocabularies match."],"exampleFix":"// before\nlet rel = Relation::parse(\"authored-by\")?; // unknown relation: authored-by\n\n// after\nlet rel = Relation::parse(\"authored_by\")?;\n// or derive from a typed value: Relation::AuthoredBy.as_str()","handlingStrategy":"type-guard","validationCode":"// Reject unknown values before touching the graph\nfn normalize_relation(s: &str) -> Option<String> {\n    let norm = s.trim().to_lowercase().replace(['-', ' '], \"_\");\n    Relation::SCHEMA_VALUES.contains(&norm.as_str()).then_some(norm)\n}\nif normalize_relation(&input).is_none() {\n    return Err(anyhow::anyhow!(\"unsupported relation '{input}'; valid: {:?}\", Relation::SCHEMA_VALUES));\n}","typeGuard":"pub fn is_known_node_type(s: &str) -> bool {\n    NodeType::SCHEMA_VALUES.contains(&s)\n}\n\npub fn is_known_relation(s: &str) -> bool {\n    Relation::SCHEMA_VALUES.contains(&s)\n}","tryCatchPattern":"// Parse user/DB input defensively\nmatch Relation::parse(&raw) {\n    Ok(rel) => graph.add_edge(&from, &to, rel)?,\n    Err(e) if e.to_string().starts_with(\"unknown relation\") => {\n        tracing::warn!(raw, \"skipping edge with unrecognized relation\");\n        continue;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never hand-build the literal; use Relation::AuthoredBy.as_str() or the SCHEMA_VALUES constants.","Normalize (trim, lowercase, '-'→'_') any human or LLM input before parse.","Validate stored vocabularies after version upgrades: SELECT DISTINCT node_type FROM nodes / DISTINCT relation FROM edges against SCHEMA_VALUES.","Keep relation vocabulary pinned per database file; migrate strings when the enum set changes."],"tags":["rust","zeroclaw","knowledge-graph","enum","parse","validation","schema-values"],"backgroundTag":"unknown-enum-variant","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}