{"record":{"id":"7375d8f89bed7a07","repo":"influxdata/influxdb","slug":"row-count-overflows-i64","errorCode":null,"errorMessage":"row count overflows i64","messagePattern":"row count overflows i64","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/parquet_file/src/metadata.rs","lineNumber":491,"sourceCode":"        let columns: Vec<_> = stats.iter().map(|v| column_id_map(&v.name)).collect();\n\n        // Extract the min/max timestamps.\n        let TimestampRange {\n            min: min_time,\n            max: max_time,\n        } = derive_min_max_time(stats);\n\n        ParquetFileParams {\n            namespace_id: self.namespace_id,\n            table_id: self.table_id,\n            partition_id,\n            partition_hash_id,\n            object_store_id: self.object_store_id,\n            min_time,\n            max_time,\n            file_size_bytes: file_size_bytes as i64,\n            compaction_level: self.compaction_level,\n            row_count: row_count.try_into().expect(\"row count overflows i64\"),\n            column_set: ColumnSet::new(columns),\n            max_l0_created_at: self.max_l0_created_at,\n            // Currently, we're only setting the `source` field if the Parquet file is being\n            // created by bulk ingest, which does not use this code path. So for now, always set\n            // `source` to `None` here.\n            source: None,\n        }\n    }\n\n    /// Estimate the memory consumption of this object and its contents\n    pub fn size(&self) -> usize {\n        // size of this structure, including inlined size + heap sizes\n        let size_without_sortkey_refs = mem::size_of_val(self)\n            + self.namespace_name.len()\n            + self.table_name.len()\n            + std::mem::size_of::<PartitionKey>();\n\n        if let Some(sort_key) = self.sort_key.as_ref() {","sourceCodeStart":473,"sourceCodeEnd":509,"githubUrl":"https://github.com/influxdata/influxdb/blob/d28e26e048401c53cbb98cf2d6ab0cf1e98048ca/core/parquet_file/src/metadata.rs#L473-L509","documentation":"to_parquet_file stores the row count as row_count.try_into().expect(\"row count overflows i64\") — a u64-to-i64 conversion that fails only above i64::MAX (~9.2 quintillion) rows. Parquet row counts originate as i64 in the footer, so a value that overflows cannot be produced by a real file; this expect is a defensive bound, effectively unreachable.","triggerScenarios":"Only a fabricated DecodedIoxParquetMetaData reporting > i64::MAX rows (hand-crafted metadata bytes or memory corruption). Genuine parquet footers cannot carry such counts.","commonSituations":"Practically never in production; conceivable in fuzz tests feeding mutated metadata blobs, or if a future format changes row-count widths.","solutions":["If hit, suspect data corruption of the metadata blob itself — re-verify the object and its checksums.","In fuzzing/harness code, bound or reject absurd row_count values before invoking to_parquet_file.","No production change is warranted; treat as an invariant assert."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// if you feed crafted metadata (fuzzing/harnesses), bound the row count first\nfn row_count_fits_i64(m: &IoxParquetMetaData) -> bool {\n    matches!(u64::try_from(m.decode().map(|d| d.row_count()).unwrap_or(0)), Ok(n) if n <= i64::MAX as u64)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["In fuzz harnesses, cap generated row_count values to i64::MAX.","Verify object integrity if this ever fires — real parquet cannot exceed i64 rows.","No production mitigation needed; treat as a defensive assert."],"tags":["rust","influxdb-iox","integer-overflow","type-conversion","unreachable-defensive-panic"],"backgroundTag":"integer-overflow-conversion","analyzedSha":"d28e26e048401c53cbb98cf2d6ab0cf1e98048ca","analyzedAt":"2026-08-16T19:53:34.623Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}