influxdata/influxdb · error · Error

specified key column

Error message

specified key column (id: {column_id}) does not exist in the table schema

What it means

This is the `KeyColumnDoesNotExist` variant of the last-cache `Error` enum. It is raised when a column supplied as a key column, referenced by numeric ColumnId, is not present in the table's schema. Key columns form the group-by dimension of a last-of-value cache, so the library validates each key id against the current table schema before constructing the cache.

Solutions

  1. Verify each key column id against the current table schema before calling create_last_cache
  2. Reference key columns by name (`KeyColumnDoesNotExistByName` path) or look up ids fresh from the schema
  3. Re-fetch the table definition after schema changes and rebuild cache configuration

Example fix

// before
let key_ids = vec![3]; // id no longer in schema
create_last_cache(db, tbl, name, Some(key_ids), None, count, ttl);
// after
let key_ids: Vec<ColumnId> = ["tag_one"].iter()
    .map(|n| table_def.schema().column_id_by_name(n).unwrap())
    .collect();
create_last_cache(db, tbl, name, Some(key_ids), None, count, ttl);
Defensive patterns

Strategy: validation

Validate before calling

fn validate_key_columns(schema: &Schema, ids: &[ColumnId]) -> Result<(), String> {
    ids.iter().find(|id| schema.field_id(**id).is_none())
        .map_or(Ok(()), |id| Err(format!("key column id {id} not in schema")))
}

Type guard

fn all_key_columns_exist(schema: &Schema, ids: &[ColumnId]) -> bool {
    ids.iter().all(|id| schema.field_id(*id).is_some())
}

Try / catch

match res {
    Err(LastCacheError::KeyColumnDoesNotExist { column_id }) => {
        eprintln!("key column id {column_id} missing; re-derive keys from current schema");
    }
    Err(e) => return Err(e.into()),
    Ok(_) => {}
}

Prevention

When it happens

Trigger: Calling `create_last_cache` / `create_from_table` with `key_columns` containing a ColumnId absent from the table schema; building a cache over a table after its key columns were dropped or re-created with new ids.

Common situations: Configuring cache key columns by id copied from an older schema after ALTER TABLE; schema drift between test and production tables; generating cache configs programmatically from stale metadata.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19). Data as JSON: /api/errors/d4d036f842312c68. Report an issue: GitHub.

Appendix: source

Thrown at influxdb3_cache/src/last_cache/mod.rs:26

mod provider;
pub use provider::{LastCacheProvider, background_catalog_update};
mod table_function;
use schema::InfluxColumnType;
pub use table_function::{LAST_CACHE_UDTF_NAME, LastCacheFunction};

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("invalid cache size")]
    InvalidCacheSize,
    #[error(
        "last cache already exists for database and table, but it was configured differently: {reason}"
    )]
    CacheAlreadyExists { reason: String },
    #[error("specified column (name: {column_name}) does not exist in the table definition")]
    ColumnDoesNotExistByName { column_name: String },
    #[error("specified column (id: {column_id}) does not exist in the table definition")]
    ColumnDoesNotExistById { column_id: ColumnId },
    #[error("specified key column (id: {column_id}) does not exist in the table schema")]
    KeyColumnDoesNotExist { column_id: ColumnId },
    #[error("specified key column (name: {column_name}) does not exist in the table schema")]
    KeyColumnDoesNotExistByName { column_name: String },
    #[error("key column must be string, int, uint, or bool types, got: {column_type}")]
    InvalidKeyColumn { column_type: InfluxColumnType },
    #[error("specified value column ({column_id}) does not exist in the table schema")]
    ValueColumnDoesNotExist { column_id: ColumnId },
    #[error("requested last cache does not exist")]
    CacheDoesNotExist,
}

impl Error {
    fn cache_already_exists(reason: impl Into<String>) -> Self {
        Self::CacheAlreadyExists {
            reason: reason.into(),
        }
    }
}

View on GitHub (pinned to 06200ef96b)