influxdata/influxdb · error

row_delete_predicate_version exceeds u64

Error message

row_delete_predicate_version exceeds u64

What it means

A `.expect(...)` panic in the v2->v3 migration while converting a `NodeSnapshot` into a `RegisterNode` record: the v2 `row_delete_predicate_version` value is converted with `u64::try_from` and asserted to fit. The type in the v2 snapshot is apparently signed/wider, and a negative or out-of-range value cannot be represented as u64 in v3.

Solutions

  1. Inspect the node entries in the v2 catalog and fix/reset `row_delete_predicate_version` to a valid non-negative version (usually 0 or 1).
  2. Restore the v2 catalog object from a known-good backup.
  3. Replace the `expect` with a fallible mapping that returns `MigrationError::Unexpected` so migration fails gracefully.
  4. Check for tooling/scripts writing sentinel (-1) versions into the v2 catalog and remove them.

Example fix

// before
.expect("row_delete_predicate_version exceeds u64"),
// after
row_delete_predicate_version: u64::try_from(self.row_delete_predicate_version)
    .map_err(|_| MigrationError::Unexpected(anyhow::anyhow!("invalid row_delete_predicate_version {}", self.row_delete_predicate_version)))?,
Defensive patterns

Strategy: validation

Validate before calling

fn row_delete_predicate_version_is_valid(v: i64) -> bool { v >= 0 }

Type guard

fn as_u64(v: i64) -> Option<u64> { u64::try_from(v).ok() }

Try / catch

// panic path; guard any code that writes this field
let version = as_u64(raw).ok_or_else(|| anyhow!("row_delete_predicate_version must be non-negative"))?;

Prevention

When it happens

Trigger: Running the v2->v3 migration when a node entry in the v2 catalog has `row_delete_predicate_version` that is negative or otherwise unrepresentable as u64 (e.g. i64::MIN, corrupt value).

Common situations: Corrupted or hand-edited v2 catalog objects; test fixtures with sentinel values like -1; catalogs written by older builds with a differently-typed version field.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19). Data as JSON: /api/errors/43c2cb9df8f2a4d8. Report an issue: GitHub.

Appendix: source

Thrown at influxdb3_catalog/src/catalog/migrations/v3.rs:268

    /// the Stopped state on apply.
    fn from_v2(&self, batch: &mut RecordBatch) {
        let registered_time_ns = match &self.state {
            NodeStateSnapshot::Running { registered_time_ns } => *registered_time_ns,
            NodeStateSnapshot::Stopped { .. } => 0,
        };

        batch.push(&RegisterNode {
            node_catalog_id: self.node_catalog_id.get(),
            node_id: self.node_id.to_string(),
            instance_id: self.instance_id.to_string(),
            registered_time_ns,
            core_count: self.core_count,
            mode: self.mode.iter().copied().map(Into::into).collect(),
            process_uuid: [0u8; 16], // placeholder -- not preserved in v2
            conn_info: self.conn_info.as_ref().map(|s| s.to_string()),
            cli_params: self.cli_params.as_ref().map(|s| s.to_string()),
            row_delete_predicate_version: u64::try_from(self.row_delete_predicate_version)
                .expect("row_delete_predicate_version exceeds u64"),
            // v2 has no concept of feature level:
            feature_level: FeatureLevel::ZERO,
        });

        if let NodeStateSnapshot::Stopped { stopped_time_ns } = &self.state {
            batch.push(&StopNode {
                node_catalog_id: self.node_catalog_id.get(),
                node_id: self.node_id.to_string(),
                stopped_time_ns: *stopped_time_ns,
                process_uuid: [0u8; 16], // placeholder -- not preserved in v2
            });
        }
    }
}

impl FromV2 for DatabaseSnapshot {
    fn from_v2(&self, batch: &mut RecordBatch) {
        let db_id = self.id.get();

View on GitHub (pinned to 06200ef96b)