zeroclaw-labs/zeroclaw · error

unknown {}: {other}

Error message

unknown {}: {other}

What it means

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.

Source

Thrown at crates/zeroclaw-memory/src/knowledge_graph.rs:46

        impl $name {
            pub const ALL: &'static [Self] = &[$(Self::$variant),+];
            pub const SCHEMA_VALUES: &'static [&'static str] = &[$($value),+];

            pub fn as_str(&self) -> &'static str {
                match self {
                    $(Self::$variant => $value),+
                }
            }

            pub fn schema_values() -> &'static [&'static str] {
                Self::SCHEMA_VALUES
            }

            pub fn parse(s: &str) -> anyhow::Result<Self> {
                match s {
                    $($value => Ok(Self::$variant),)+
                    other => anyhow::bail!(
                        "unknown {}: {other}",
                        $error_label
                    ),
                }
            }
        }
    };
}

knowledge_enum! {
    /// The kind of knowledge captured in a node.
    pub enum NodeType {
        Pattern => "pattern",
        Decision => "decision",
        Lesson => "lesson",
        Expert => "expert",
        Technology => "technology",
        Client => "client",

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. 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.
  2. Normalize input before parsing: trim, lowercase, and convert '-' or spaces to '_' for relation names.
  3. 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.
  4. Pin your ZeroClaw version when moving graph databases between installs so enum vocabularies match.

Example fix

// before
let rel = Relation::parse("authored-by")?; // unknown relation: authored-by

// after
let rel = Relation::parse("authored_by")?;
// or derive from a typed value: Relation::AuthoredBy.as_str()
Defensive patterns

Strategy: type-guard

Validate before calling

// Reject unknown values before touching the graph
fn normalize_relation(s: &str) -> Option<String> {
    let norm = s.trim().to_lowercase().replace(['-', ' '], "_");
    Relation::SCHEMA_VALUES.contains(&norm.as_str()).then_some(norm)
}
if normalize_relation(&input).is_none() {
    return Err(anyhow::anyhow!("unsupported relation '{input}'; valid: {:?}", Relation::SCHEMA_VALUES));
}

Type guard

pub fn is_known_node_type(s: &str) -> bool {
    NodeType::SCHEMA_VALUES.contains(&s)
}

pub fn is_known_relation(s: &str) -> bool {
    Relation::SCHEMA_VALUES.contains(&s)
}

Try / catch

// Parse user/DB input defensively
match Relation::parse(&raw) {
    Ok(rel) => graph.add_edge(&from, &to, rel)?,
    Err(e) if e.to_string().starts_with("unknown relation") => {
        tracing::warn!(raw, "skipping edge with unrecognized relation");
        continue;
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/06fdf8cb6023dcd8. Report an issue: GitHub.