zeroclaw-labs/zeroclaw · error
knowledge graph node limit reached ({}/{})
Error message
knowledge graph node limit reached ({}/{}) What it means
KnowledgeGraph is a SQLite-backed graph with a hard node capacity set at construction (KnowledgeGraph::new(db_path, max_nodes)). add_node first runs SELECT COUNT(*) FROM nodes and refuses the insert — before touching tags or writing — once the total reaches max_nodes, reporting (current, max). This is a deliberate bounding of graph growth (disk and FTS cost), not corruption: the call simply fails and nothing is written.
Source
Thrown at crates/zeroclaw-memory/src/knowledge_graph.rs:214
max_nodes,
})
}
/// Add a node to the graph. Returns the generated node id.
pub fn add_node(
&self,
node_type: NodeType,
title: &str,
content: &str,
tags: &[String],
source_project: Option<&str>,
) -> anyhow::Result<String> {
let conn = self.conn.lock();
// Enforce max_nodes limit.
let count: usize = conn.query_row("SELECT COUNT(*) FROM nodes", [], |r| r.get(0))?;
if count >= self.max_nodes {
anyhow::bail!(
"knowledge graph node limit reached ({}/{})",
count,
self.max_nodes
);
}
// Reject tags containing commas since comma is the separator in storage.
for tag in tags {
if tag.contains(',') {
anyhow::bail!(
"tag '{}' contains a comma, which is used as the tag separator",
tag
);
}
}
let id = Uuid::new_v4().to_string();
let now = Utc::now().to_rfc3339();View on GitHub (pinned to 88bb9c8533)
Solutions
- Check the pair in the message: if the cap is simply too small for real use, open the graph with a larger max_nodes in KnowledgeGraph::new.
- Prune or consolidate stale nodes (old interactions, superseded lessons) to bring COUNT(*) below the limit, then retry.
- Before adding in bulk, read graph.stats()?.total_nodes and budget the import against max_nodes instead of failing mid-batch.
- If growth is the norm, schedule periodic pruning/archival so add_node never reaches the ceiling.
Example fix
// before
let graph = KnowledgeGraph::new(&path, 100)?;
// ... after 100 captures:
graph.add_node(NodeType::Lesson, "t", "c", &[], None)?; // node limit reached (100/100)
// after: size the cap to real usage and prune before imports
let graph = KnowledgeGraph::new(&path, 10_000)?;
if graph.stats()?.total_nodes + batch_len >= 10_000 { /* prune first */ } Defensive patterns
Strategy: validation
Validate before calling
// Check headroom before writing
let stats = graph.stats()?;
if stats.total_nodes >= max_nodes {
return Err(anyhow::anyhow!(
"graph at capacity ({}/{}): prune before adding", stats.total_nodes, max_nodes
));
}
let id = graph.add_node(node_type, title, content, tags, source)?; Try / catch
// In capture loops: capacity errors mean 'shed load', not 'crash'
match graph.add_node(node_type, title, content, tags, src) {
Ok(id) => Some(id),
Err(e) if e.to_string().contains("node limit reached") => {
tracing::warn!(error = %e, "knowledge graph full; dropping capture");
None
}
Err(e) => return Err(e),
} Prevention
- Size max_nodes from expected capture rate times retention horizon, not a round test number.
- Monitor stats().total_nodes and alert before it approaches max_nodes.
- Prune low-value node types (e.g. old interactions) on a schedule so the shared budget is not exhausted by one type.
- For bulk imports, count first and chunk the import to stop cleanly below the cap.
When it happens
Trigger: Calling add_node (including via the capture handler) on a graph whose nodes table already has max_nodes or more rows. The count is over ALL node types, so heavy capture of one type (e.g. interactions) exhausts the budget for every other type. Also hit when the constructor was given a small max_nodes for testing and production data outgrew it.
Common situations: Long-running agents that capture knowledge every turn eventually fill the cap; a copied-to-production config with a tiny test limit; bulk-import scripts (migrating another graph) exceeding the ceiling mid-run; test suites asserting the limit (add_node tests).
Related errors
- unknown {}: {other}
- tag '{}' contains a comma, which is used as the tag separato
- source node not found: {from_id}
- target node not found: {to_id}
- subgraph depth must be greater than 0
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/7118c7a0484c687a.
Report an issue: GitHub.