influxdata/influxdb · critical
there should not already be a node
Error message
there should not already be a node
What it means
A panic from `.expect()` when inserting a brand-new NodeDefinition in the else-branch of CreateNode replay. The code believes no node with this node_catalog_id exists and calls `insert()`, but the repository's insert returned a conflict/None, i.e. a node with that id already exists. It guards against duplicate node ids corrupting the node catalog.
Solutions
- Deduplicate node batches before applying; make create idempotent by checking `get_by_id` first.
- Audit the WAL for duplicate CreateNode entries covering the same node_catalog_id.
- If snapshot and WAL overlap, fix the snapshot/compaction boundaries so operations aren't replayed twice.
- Replace the expect with a defensive check that logs and skips or converts to update on collision.
Example fix
// before
self.nodes
.insert(node_batch.node_catalog_id, new_node)
.expect("there should not already be a node");
// after
if self.nodes.get_by_id(&node_batch.node_catalog_id).is_none() {
self.nodes
.insert(node_batch.node_catalog_id, new_node)
.expect("there should not already be a node");
} // else: idempotent no-op or update existing Defensive patterns
Strategy: validation
Validate before calling
assert!(nodes.get_by_id(&node_batch.node_catalog_id).is_none(), "node already exists; make create idempotent");
Type guard
fn is_new_node(nodes: &Nodes, id: NodeId) -> bool { nodes.get_by_id(&id).is_none() } Prevention
- Deduplicate node batches before applying them
- Make CreateNode idempotent: skip or update when the id already exists
- Fix snapshot/WAL boundaries to avoid double replay
- Test replay with duplicated create operations
When it happens
Trigger: Replaying a CreateNode batch whose node_catalog_id collides with an already-present node — e.g. duplicate operations in the batch log, or a replay that re-applies an operation already applied to the repository.
Common situations: Double-replayed WAL segments after an unclear shutdown, snapshot+WAL overlap causing the same create to be applied twice, or a duplicated batch produced by a buggy writer.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- existing database should be updated
- existing node should update
- field does not exist
- field family ID and name don't exist
- no duplicate tag
AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19).
Data as JSON: /api/errors/c56b2f763668cfaf.
Report an issue: GitHub.
Appendix: source
Thrown at influxdb3_catalog/src/catalog/versions/v2.rs:1732
.update(node_batch.node_catalog_id, node)
.expect("existing node should update");
} else {
let new_node = Arc::new(NodeDefinition {
node_id: Arc::clone(node_id),
node_catalog_id: node_batch.node_catalog_id,
instance_id: Arc::clone(instance_id),
mode: mode.clone(),
core_count: *core_count,
state: NodeState::Running {
registered_time_ns: *registered_time_ns,
},
conn_info: conn_info.as_ref().map(|s| Arc::from(s.as_str())),
cli_params: cli_params.as_ref().map(|s| Arc::from(s.as_str())),
row_delete_predicate_version: *row_delete_predicate_version,
});
self.nodes
.insert(node_batch.node_catalog_id, new_node)
.expect("there should not already be a node");
}
true
}
NodeCatalogOp::StopNode(StopNodeLog {
stopped_time_ns, ..
}) => match self.nodes.get_by_id(&node_batch.node_catalog_id) {
Some(mut new_node) => {
let n = Arc::make_mut(&mut new_node);
n.state = NodeState::Stopped {
stopped_time_ns: *stopped_time_ns,
};
self.nodes
.update(node_batch.node_catalog_id, new_node)
.expect("there should be a node to update");
true
}
None => {
warn!(View on GitHub (pinned to 06200ef96b)