influxdata/influxdb · error · Error

key column must be string, int, uint, or bool types, got

Error message

key column must be string, int, uint, or bool types, got: {column_type}

What it means

This is the `InvalidKeyColumn` variant of the last-cache `Error` enum. Last-of-value cache key columns must be string, int, uint, or bool (tag-like, groupable types); it is raised when a column designated as a key column has an unsupported InfluxColumnType such as float or timestamp. The type check happens against the table schema at cache creation.

Solutions

  1. Choose a string/int/uint/bool column (typically a tag) as the key column
  2. Remove the unsupported column from `key_columns` and key the cache by tags only
  3. If the offending column must be a key, change its schema type to an allowed one and recreate the table/cache

Example fix

// before
// 'temperature' is a float field -> InvalidKeyColumn
create_last_cache(db, "sensors", "latest", Some(&["location", "temperature"]), None, 10, None);
// after
create_last_cache(db, "sensors", "latest", Some(&["location"]), None, 10, None);
Defensive patterns

Strategy: validation

Validate before calling

fn key_columns_have_allowed_type(schema: &Schema, names: &[&str]) -> Result<(), String> {
    for n in names {
        let id = schema.field_name_to_id(n)?;
        let t = schema.field_type_by_id(id).unwrap();
        if !matches!(t,
            InfluxColumnType::Tag
            | InfluxColumnType::Field(FieldType::Int)
            | InfluxColumnType::Field(FieldType::UInt)
            | InfluxColumnType::Field(FieldType::Boolean))
        {
            return Err(format!("key column '{n}' has unsupported type {t:?}"));
        }
    }
    Ok(())
}

Type guard

fn is_valid_key_type(t: &InfluxColumnType) -> bool {
    matches!(t,
        InfluxColumnType::Tag
        | InfluxColumnType::Field(FieldType::Int)
        | InfluxColumnType::Field(FieldType::UInt)
        | InfluxColumnType::Field(FieldType::Boolean))
}

Try / catch

match res {
    Err(LastCacheError::InvalidKeyColumn { column_type }) => {
        eprintln!("key column type {column_type} unsupported; use string/int/uint/bool");
    }
    Err(e) => return Err(e.into()),
    Ok(_) => {}
}

Prevention

When it happens

Trigger: Calling `create_last_cache` with a `key_columns` entry that resolves to a float or time column in the table schema; using a measurement/value field as a group-by key for the cache.

Common situations: Configuring a numeric measurement field (e.g. a float 'value' column) as a cache key; switching a column's type in the schema after the cache config was written; misunderstanding that key columns must be tag-like, not values.

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/95c2958e47df8b12. Report an issue: GitHub.

Appendix: source

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

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(),
        }
    }
}

#[cfg(test)]
mod tests;

View on GitHub (pinned to 06200ef96b)