{"record":{"id":"ee6801d6648213e2","repo":"influxdata/influxdb","slug":"last-cache-size-overflows-u64","errorCode":null,"errorMessage":"last cache size overflows u64","messagePattern":"last cache size overflows u64","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"influxdb3_catalog/src/catalog/migrations/v3.rs","lineNumber":491,"sourceCode":"            database_id: db_id,\n            table_id,\n            deletion_time_ns,\n            hard_deletion_time_ns: table.hard_delete_time,\n            hard_delete_scope: table.hard_delete_scope.as_ref().map(Into::into),\n        });\n    }\n}\n\nfn synthesize_last_cache(cache: &LastCacheSnapshot, db_id: u32, batch: &mut RecordBatch) {\n    batch.push(&CreateLastCache {\n        db_id,\n        table_id: cache.table_id.get(),\n        id: cache.id.get(),\n        node_spec: (&cache.node_spec).into(),\n        name: cache.name.to_string(),\n        key_columns: cache.keys.iter().copied().map(Into::into).collect(),\n        value_columns: (&cache.vals).into(),\n        count: u64::try_from(cache.n).expect(\"last cache size overflows u64\"),\n        ttl_seconds: cache.ttl,\n    });\n}\n\nimpl FromV2 for TokenInfoSnapshot {\n    /// A token with a single wildcard-everywhere permission is an admin\n    /// token; emit `CreateAdminToken`. Anything else is resource-scoped and\n    /// carries its permissions as-is in `CreateResourceScopedToken`.\n    fn from_v2(&self, batch: &mut RecordBatch) {\n        let token_id = self.id.get();\n        let expiry = optional_expiry(self.expiry);\n        if is_admin_permissions(&self.permissions) {\n            batch.push(&CreateAdminToken {\n                token_id,\n                name: self.name.to_string(),\n                hash: self.hash.clone(),\n                created_at: self.created_at,\n                updated_at: self.updated_at,","sourceCodeStart":473,"sourceCodeEnd":509,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/influxdb3_catalog/src/catalog/migrations/v3.rs#L473-L509","documentation":"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.","triggerScenarios":"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.","commonSituations":"Corrupted v2 catalog objects; fixtures using -1 as 'unset' cache size; catalogs written by tooling that didn't validate the size field.","solutions":["Inspect the last cache entries in the v2 catalog and correct the `n` field to a valid non-negative cache size.","Restore the v2 catalog object from backup.","Make the conversion fallible (return `MigrationError::Unexpected`) instead of panicking via `expect`.","Fix whatever writer produced the invalid size value so no new corrupt catalogs are created."],"exampleFix":"// before\ncount: u64::try_from(cache.n).expect(\"last cache size overflows u64\"),\n// after\ncount: u64::try_from(cache.n).map_err(|_| {\n    MigrationError::Unexpected(anyhow::anyhow!(\"last cache {} size {} overflows u64\", cache.name, cache.n))\n})?,","handlingStrategy":"validation","validationCode":"fn cache_size_is_valid(n: i64) -> bool { n >= 0 }","typeGuard":"fn to_u64(n: i64) -> Option<u64> { u64::try_from(n).ok() }","tryCatchPattern":"// panic path; pre-validate v2 cache entries before migration\nlet count = to_u64(cache.n).ok_or_else(|| anyhow!(\"last cache '{}' has invalid size\", cache.name))?;","preventionTips":["Reject non-negative-only violations at write time: cache sizes must be >= 0.","Fix tooling that uses -1 as an 'unset' marker for cache size.","Audit v2 last-cache snapshots before migrating.","Restore corrupted catalogs from backup rather than patching values in place."],"tags":["influxdb3","catalog-migration","overflow","last-cache","rust"],"backgroundTag":"value-out-of-range","analyzedSha":"06200ef96ba82c5f6727e5038a83af8e722c6875","analyzedAt":"2026-09-19T12:55:30.003Z","contentChangedAt":"2026-09-19T12:55:30.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}