{"record":{"id":"81d457831a1be2f3","repo":"influxdata/influxdb","slug":"cache-error-0","errorCode":null,"errorMessage":"cache error: {0}","messagePattern":"cache error: (.+?)","errorType":"exception","errorClass":"ProviderError","httpStatus":null,"severity":"error","filePath":"influxdb3_cache/src/distinct_cache/provider.rs","lineNumber":17,"sourceCode":"use std::{collections::HashMap, sync::Arc, time::Duration};\n\nuse super::{\n    CacheError,\n    cache::{CreateDistinctCacheArgs, DistinctCache},\n};\nuse arrow::datatypes::SchemaRef;\nuse influxdb3_catalog::catalog::{Catalog, CatalogEvent, CatalogUpdateReceiver, IfNotDeleted};\nuse influxdb3_id::{DbId, DistinctCacheId, TableId};\nuse influxdb3_wal::{WalContents, WalOp};\nuse iox_time::TimeProvider;\nuse observability_deps::tracing::error;\nuse parking_lot::RwLock;\n\n#[derive(Debug, thiserror::Error)]\npub enum ProviderError {\n    #[error(\"cache error: {0}\")]\n    Cache(#[from] CacheError),\n    #[error(\"cache not found\")]\n    CacheNotFound,\n    #[error(\"unexpected error: {0:#}\")]\n    Unexpected(#[from] anyhow::Error),\n}\n\n/// Triple nested map for storing a multiple distinct value caches per table.\n///\n/// That is, the map nesting is `database -> table -> cache id`\ntype CacheMap = RwLock<HashMap<DbId, HashMap<TableId, HashMap<DistinctCacheId, DistinctCache>>>>;\n\n/// Provides the distinct value caches for the running instance of InfluxDB\n#[derive(Debug)]\npub struct DistinctCacheProvider {\n    pub(crate) time_provider: Arc<dyn TimeProvider>,\n    pub(crate) catalog: Arc<Catalog>,\n    pub(crate) cache_map: CacheMap,","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/influxdb3_cache/src/distinct_cache/provider.rs#L1-L35","documentation":"ProviderError::Cache wraps a CacheError (via #[from]) when a distinct-cache level failure propagates through the cache provider. It is the provider-layer envelope around errors like EmptyColumnSet, NonTagOrStringColumn, or ConfigurationMismatch.","triggerScenarios":"Any provider API call (new_cache, get_cache, etc.) whose underlying DistinctCache operation returns a CacheError, automatically converted into ProviderError::Cache.","commonSituations":"Creating caches with empty or non-string column lists, or redefining an existing cache with mismatched configuration, observed at the provider/HTTP API layer.","solutions":["Match on ProviderError::Cache and handle the inner CacheError variant to produce a precise user message","Fix the underlying cause per the inner error (valid columns, non-empty set, no conflicting overwrite)","Log the full error chain for diagnostics"],"exampleFix":"// before\nmatch provider.new_cache(table_id, cols) { Ok(c) => c, Err(e) => return Err(anyhow!(e)) }\n// after\nmatch provider.new_cache(table_id, cols) {\n    Ok(c) => c,\n    Err(ProviderError::Cache(inner)) => bail!(\"invalid distinct cache request: {inner}\"),\n    Err(ProviderError::CacheNotFound) => bail!(\"cache does not exist\"),\n    Err(e) => return Err(e.into()),\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Rust\nmatch provider.new_cache(table_id, cols) {\n    Ok(cache) => cache,\n    Err(ProviderError::Cache(inner)) => bail!(\"distinct cache rejected: {inner}\"),\n    Err(ProviderError::CacheNotFound) => bail!(\"cache not found\"),\n    Err(ProviderError::Unexpected(e)) => bail!(\"unexpected: {e:#}\"),\n}","preventionTips":["Always destructure ProviderError instead of stringifying, to surface the inner CacheError","Validate cache inputs (non-empty, tag/string columns) before provider calls","Log full error chains including sources for diagnostics"],"tags":["distinct-cache","error-wrapping","rust","influxdb3"],"backgroundTag":"invalid-argument-value","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"}