{"record":{"id":"4c0a6736fd130487","repo":"influxdata/influxdb","slug":"must-pass-a-non-empty-set-of-column-ids","errorCode":null,"errorMessage":"must pass a non-empty set of column ids","messagePattern":"must pass a non-empty set of column ids","errorType":"validation","errorClass":"CacheError","httpStatus":null,"severity":"error","filePath":"influxdb3_cache/src/distinct_cache/cache.rs","lineNumber":24,"sourceCode":"\nuse anyhow::Context;\nuse arrow::{\n    array::{ArrayRef, RecordBatch, StringViewBuilder},\n    datatypes::{DataType, Field, SchemaBuilder, SchemaRef},\n    error::ArrowError,\n};\nuse indexmap::IndexMap;\nuse influxdb3_catalog::catalog::legacy;\nuse influxdb3_catalog::catalog::{MaxAge, MaxCardinality, TableDefinition};\nuse influxdb3_id::{ColumnId, ColumnIdentifier};\nuse influxdb3_wal::{FieldData, Row};\nuse iox_time::TimeProvider;\nuse observability_deps::tracing::debug;\nuse schema::{InfluxColumnType, InfluxFieldType};\n\n#[derive(Debug, thiserror::Error)]\npub enum CacheError {\n    #[error(\"must pass a non-empty set of column ids\")]\n    EmptyColumnSet,\n    #[error(\n        \"cannot use a column of type {attempted} in a distinct value cache, only \\\n                    tags and string fields can be used\"\n    )]\n    NonTagOrStringColumn { attempted: InfluxColumnType },\n    #[error(\"cannot overwrite an an existing cache: {message}\")]\n    ConfigurationMismatch { message: String },\n    #[error(\"unexpected error: {0}\")]\n    Unexpected(#[from] anyhow::Error),\n}\n\n/// A cache for storing distinct values for a set of columns in a table\n#[derive(Debug)]\npub(crate) struct DistinctCache {\n    time_provider: Arc<dyn TimeProvider>,\n    /// The maximum number of unique value combinations in the cache\n    max_cardinality: usize,","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/influxdb3_cache/src/distinct_cache/cache.rs#L6-L42","documentation":"CacheError::EmptyColumnSet is returned when creating a distinct value cache with an empty set of column ids. A distinct cache must track at least one column, otherwise it has nothing to deduplicate, so the constructor rejects the request upfront.","triggerScenarios":"Calling the distinct cache creation API (CREATE DISTINCT CACHE or the provider's create_cache/new_cache call) with an empty column id list.","commonSituations":"SQL statements where the column list is built dynamically from empty user input, or JSON config where the 'columns' array was omitted/empty.","solutions":["Supply at least one column id when creating the cache","Validate the column list length before invoking the cache creation API","If columns are derived dynamically, return a user-facing error early when the derived list is empty"],"exampleFix":"// before\nprovider.new_cache(table_id, columns) // columns is empty\n// after\nassert!(!columns.is_empty(), \"distinct cache requires at least one column\");\nprovider.new_cache(table_id, columns)","handlingStrategy":"validation","validationCode":"fn valid_column_set(col_ids: &[ColumnId]) -> bool {\n    !col_ids.is_empty()\n}","typeGuard":null,"tryCatchPattern":"// Rust\nmatch provider.new_cache(table_id, cols) {\n    Err(ProviderError::Cache(CacheError::EmptyColumnSet)) => bail!(\"distinct cache requires at least one column id\"),\n    other => other,\n}","preventionTips":["Guard dynamic column-list construction so empty input fails early with a clear message","Require at least one column in SQL/JSON forms for CREATE DISTINCT CACHE","Unit-test cache creation with empty input to confirm your validation"],"tags":["validation","distinct-cache","rust","influxdb3"],"backgroundTag":"empty-required-field","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"}