influxdata/influxdb · error

last cache size overflows u64

Error message

last cache size overflows u64

What it means

A `.expect(...)` panic in the v2->v3 migration when converting a v2 last cache snapshot into a `CreateLastCache` record: `u64::try_from(cache.n)` asserts the cache size (`n`, likely a signed or smaller integer) fits into u64. The v3 catalog's `count` field is u64, and a negative/overflowing value cannot be converted.

Solutions

  1. Inspect the last cache entries in the v2 catalog and correct the `n` field to a valid non-negative cache size.
  2. Restore the v2 catalog object from backup.
  3. Make the conversion fallible (return `MigrationError::Unexpected`) instead of panicking via `expect`.
  4. Fix whatever writer produced the invalid size value so no new corrupt catalogs are created.

Example fix

// before
count: u64::try_from(cache.n).expect("last cache size overflows u64"),
// after
count: u64::try_from(cache.n).map_err(|_| {
    MigrationError::Unexpected(anyhow::anyhow!("last cache {} size {} overflows u64", cache.name, cache.n))
})?,
Defensive patterns

Strategy: validation

Validate before calling

fn cache_size_is_valid(n: i64) -> bool { n >= 0 }

Type guard

fn to_u64(n: i64) -> Option<u64> { u64::try_from(n).ok() }

Try / catch

// panic path; pre-validate v2 cache entries before migration
let count = to_u64(cache.n).ok_or_else(|| anyhow!("last cache '{}' has invalid size", cache.name))?;

Prevention

When it happens

Trigger: Running the v2->v3 migration when a last cache in the v2 catalog has `n` (cache size/count) that is negative or exceeds u64 — realistically only from corrupt data, sentinel values like -1, or hostile/hand-edited snapshots.

Common situations: Corrupted v2 catalog objects; fixtures using -1 as 'unset' cache size; catalogs written by tooling that didn't validate the size 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/ee6801d6648213e2. Report an issue: GitHub.

Appendix: source

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

            database_id: db_id,
            table_id,
            deletion_time_ns,
            hard_deletion_time_ns: table.hard_delete_time,
            hard_delete_scope: table.hard_delete_scope.as_ref().map(Into::into),
        });
    }
}

fn synthesize_last_cache(cache: &LastCacheSnapshot, db_id: u32, batch: &mut RecordBatch) {
    batch.push(&CreateLastCache {
        db_id,
        table_id: cache.table_id.get(),
        id: cache.id.get(),
        node_spec: (&cache.node_spec).into(),
        name: cache.name.to_string(),
        key_columns: cache.keys.iter().copied().map(Into::into).collect(),
        value_columns: (&cache.vals).into(),
        count: u64::try_from(cache.n).expect("last cache size overflows u64"),
        ttl_seconds: cache.ttl,
    });
}

impl FromV2 for TokenInfoSnapshot {
    /// A token with a single wildcard-everywhere permission is an admin
    /// token; emit `CreateAdminToken`. Anything else is resource-scoped and
    /// carries its permissions as-is in `CreateResourceScopedToken`.
    fn from_v2(&self, batch: &mut RecordBatch) {
        let token_id = self.id.get();
        let expiry = optional_expiry(self.expiry);
        if is_admin_permissions(&self.permissions) {
            batch.push(&CreateAdminToken {
                token_id,
                name: self.name.to_string(),
                hash: self.hash.clone(),
                created_at: self.created_at,
                updated_at: self.updated_at,

View on GitHub (pinned to 06200ef96b)