influxdata/influxdb · error

column id in series key should be valid

Error message

column id in series key should be valid

What it means

A `.expect(...)` panic in the catalog's `create_last_cache` update path: when value/key columns are not explicitly given, the cache key columns are derived from the table's `series_key` column ids, and each id is looked up in `column_definition_by_id`. The assertion states every series-key column id must have a definition; a lookup miss means the table's series_key references a column that does not exist in its own definition map.

Solutions

  1. Pass explicit `key_columns` to `create_last_cache` so the series-key derivation path (and its fragile lookup) is skipped.
  2. Inspect the table's schema in the catalog and repair/remove the dangling series_key entry referencing the missing column id.
  3. Restore the affected table/catalog from a consistent backup.
  4. Replace the `expect` with a proper error (e.g. `KeyColumnDoesNotExistByName`) so create_last_cache fails gracefully on inconsistent schemas.

Example fix

// before
.expect("column id in series key should be valid")
// after
.ok_or_else(|| anyhow!("series key references missing column id {}", ColumnIdentifier::tag(*id)))?
Defensive patterns

Strategy: validation

Validate before calling

// verify every series_key id resolves before calling create_last_cache without key_columns
for id in &table.series_key {
    assert!(
        table.column_definition_by_id(&ColumnIdentifier::tag(*id)).is_some(),
        "series_key references missing column id {id}"
    );
}

Type guard

fn series_key_resolves(tbl: &TableSnapshot) -> bool {
    tbl.series_key.iter().all(|id| tbl.column_definition_by_id(&ColumnIdentifier::tag(*id)).is_some())
}

Try / catch

// panic path; pass explicit key columns when the schema is suspect
if !series_key_resolves(&tbl) {
    create_last_cache(table, /* explicit key_columns */, value_columns)?;
}

Prevention

When it happens

Trigger: Calling `create_last_cache` without explicit key columns on a table whose `series_key` contains a column id missing from `column_definition_by_id` — i.e. catalog inconsistency (stale/dangling series_key after a column drop or partial schema update).

Common situations: Catalogs mutated by older/buggy versions that dropped columns without cleaning series_key; hand-restored or merged catalog snapshots; migrations that rebuilt column maps but not series keys.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at influxdb3_catalog/src/catalog/versions/v2/update.rs:954

                                    )
                                    .as_str(),
                                )
                            })
                            .and_then(|def| {
                                if is_valid_last_cache_key_col(&def) {
                                    Ok((def.id(), name.as_ref().to_string()))
                                } else {
                                    Err(CatalogError::InvalidLastCacheKeyColumnType)
                                }
                            })
                    })
                    .collect::<Result<(Vec<ColumnIdentifier>, Vec<String>)>>()?
            } else {
                tbl.series_key
                    .iter()
                    .map(|id| {
                        tbl.column_definition_by_id(&ColumnIdentifier::tag(*id))
                            .expect("column id in series key should be valid")
                    })
                    .map(|def| Ok((def.id(), def.name().to_string())))
                    .collect::<Result<(Vec<ColumnIdentifier>, Vec<String>)>>()?
            };

            let value_columns = if let Some(value_columns) = value_columns {
                let columns = value_columns
                    .iter()
                    .map(|name| {
                        tbl.column_definition(name.as_ref())
                            .map(|def| def.id())
                            .ok_or_else(|| {
                                CatalogError::invalid_configuration(
                                    format!(
                                        "invalid value column provided: {name}",
                                        name = name.as_ref()
                                    )
                                    .as_str(),

View on GitHub (pinned to 06200ef96b)