{"record":{"id":"fa73b37332ff8f5b","repo":"nautechsystems/nautilus_trader","slug":"negative-minimum-value-min-for-column-column-n","errorCode":null,"errorMessage":"Negative minimum value {min} for column '{column_name}'","messagePattern":"Negative minimum value (.+?) for column '(.+?)'","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/persistence/src/parquet.rs","lineNumber":465,"sourceCode":"                            overall_max_value = Some(max_value);\n                        }\n                    } else {\n                        anyhow::bail!(\"Warning: Column name '{column_name}' is not of type i64.\");\n                    }\n                } else {\n                    anyhow::bail!(\n                        \"Warning: Statistics not available for column '{column_name}' in row group {i}.\"\n                    );\n                }\n            }\n        }\n    }\n\n    // Return the min/max pair if both are available\n    if let (Some(min), Some(max)) = (overall_min_value, overall_max_value) {\n        Ok((\n            u64::try_from(min).map_err(|_| {\n                anyhow::anyhow!(\"Negative minimum value {min} for column '{column_name}'\")\n            })?,\n            u64::try_from(max).map_err(|_| {\n                anyhow::anyhow!(\"Negative maximum value {max} for column '{column_name}'\")\n            })?,\n        ))\n    } else {\n        anyhow::bail!(\n            \"Column '{column_name}' not found or has no Int64 statistics in any row group.\"\n        )\n    }\n}\n\n/// Creates an object store from a URI string with optional storage options.\n///\n/// Supports multiple cloud storage providers:\n/// - AWS S3: `s3://bucket/path`\n/// - Google Cloud Storage: `gs://bucket/path` or `gcs://bucket/path`\n/// - Azure Blob Storage: `az://account/container/path` or `abfs://container@account.dfs.core.windows.net/path`","sourceCodeStart":447,"sourceCodeEnd":483,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/persistence/src/parquet.rs#L447-L483","documentation":"min_max_from_parquet_metadata_object_store reads Int64 min/max statistics from Parquet metadata and returns them as an unsigned (u64) pair. When the minimum statistic is negative it cannot be represented as u64, so the conversion fails and this anyhow error is thrown.","triggerScenarios":"Calling min_max_from_parquet_metadata / min_max_from_parquet_metadata_object_store on a Parquet file whose Int64 column statistics contain a negative minimum (e.g. signed deltas, PnL-like or negative-timestamp columns).","commonSituations":"Pointing the persistence layer at a catalog/data column that stores signed values; assuming all persisted Int64 columns are non-negative (timestamps, sequence numbers); stale or hand-crafted Parquet files written by other tooling.","solutions":["Ensure the queried column stores only non-negative Int64 values before calling the function","Catch the error and fall back to a signed scan of the column data instead of statistics","Inspect the Parquet metadata with pyarrow/parquet-tools to confirm the column's min statistic before use","If the column legitimately needs negatives, this API does not support it; use a different retrieval path"],"exampleFix":"// before\nlet (min, max) = min_max_from_parquet_metadata(&meta, \"pnl\")?;\n// after\nmatch min_max_from_parquet_metadata(&meta, \"pnl\") {\n    Ok((min, max)) => (min, max),\n    Err(e) if e.to_string().contains(\"Negative minimum value\") =>\n        return Err(anyhow::anyhow!(\"column 'pnl' holds signed data; use signed statistics API\")),\n    Err(e) => return Err(e),\n}","handlingStrategy":"validation","validationCode":"// rust: check statistics sign before calling\nlet stats_min = /* i64 min from metadata */;\nanyhow::ensure!(stats_min >= 0, \"column '{}' has negative min; unsigned API unsupported\", column_name);\nlet (min, max) = min_max_from_parquet_metadata(&meta, column_name)?;","typeGuard":"fn is_non_negative_i64(v: i64) -> bool { v >= 0 }","tryCatchPattern":"match min_max_from_parquet_metadata(&meta, column) {\n    Ok(pair) => pair,\n    Err(e) => { warn!(\"min/max unavailable for {column}: {e}\"); fallback_scan(column) }\n}","preventionTips":["Only use this API on columns guaranteed non-negative (timestamps, sequence numbers)","Inspect Parquet statistics with pyarrow before wiring a new column into persistence","Add a unit test with negative-statistics fixture data to catch schema drift"],"tags":["parquet","rust","statistics","conversion"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}