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

  1. Deduplicate node batches before applying; make create idempotent by checking `get_by_id` first.
  2. Audit the WAL for duplicate CreateNode entries covering the same node_catalog_id.
  3. If snapshot and WAL overlap, fix the snapshot/compaction boundaries so operations aren't replayed twice.
  4. 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

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


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)