influxdata/influxdb · error · CatalogError

Series key mismatch on table

Error message

Series key mismatch on table {table_name}. Existing table has {existing}

What it means

InfluxDB 3's catalog enforces that a table's series key (the set of tag columns identifying a series) is fixed once the table is created. This error is thrown when a write attempt supplies data whose series key columns have types that conflict with the existing table definition, either a different key composition or an incompatible InfluxColumnType for an existing key column. It prevents silently corrupting the table schema.

Solutions

  1. Inspect the existing table schema (SHOW or the catalog) and align your writes so tag columns exactly match the existing series key.
  2. Fix the type of conflicting data on the client side (cast the value to the existing column's InfluxColumnType) before writing.
  3. If the schema is genuinely wrong, create a new table (new measurement name) with the desired series key and rewrite/replay data into it; series keys cannot be altered in place.
  4. Drop the table (if acceptable to lose data) and rewrite with the correct series key so it is recreated with the intended schema.

Example fix

// before: line protocol with tag set that mismatches the table's series key
weather,location=nyc temp=72
// after: match the existing table's declared series key columns exactly
weather,location=nyc,region=east temp=72
Defensive patterns

Strategy: validation

Validate before calling

// Fetch the table schema and compare your write's tag set/types before writing
const schema = await client.getTableSchema(db, table);
const myTags = Object.keys(myLineTags).sort();
const existingKey = schema.seriesKeyColumns.sort();
if (JSON.stringify(myTags) !== JSON.stringify(existingKey)) {
  throw new Error(`series key mismatch: got [${myTags}], table has [${existingKey}]`);
}

Type guard

function hasMatchingSeriesKey(myTags, existingKey) {
  return Array.isArray(existingKey) &&
    myTags.length === existingKey.length &&
    [...myTags].sort().every((t, i) => t === [...existingKey].sort()[i]);
}

Try / catch

try {
  await client.write(db, lines);
} catch (e) {
  if (String(e).includes('Series key mismatch')) {
    // refetch schema, realign tags/types, then retry once
  } else throw e;
}

Prevention

When it happens

Trigger: Writing lines via the line protocol / v1 / v3 write APIs where the tag set for the target table differs from the table's declared series key, or where a series key column's type differs from the existing InfluxColumnType (e.g. writing a field value into what was defined as a tag column, or a string vs integer conflict).

Common situations: Changing the tag set in a client's line protocol output after the table already exists; a script writing the same measurement with slightly different tag names; migrating data from InfluxDB 1.x/2.x where tags and fields were reshaped; typos in tag keys causing them to be treated as new series key columns.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at influxdb3_catalog/src/error.rs:197

        db_name: Arc<str>,
        table_name: Arc<str>,
    },

    #[error(
        "Field type mismatch on table {} column {}. Existing column is {} but attempted to add {}",
        table_name,
        column_name,
        existing,
        attempted
    )]
    FieldTypeMismatch {
        table_name: String,
        column_name: String,
        existing: InfluxColumnType,
        attempted: InfluxColumnType,
    },

    #[error(
        "Series key mismatch on table {}. Existing table has {}",
        table_name,
        existing
    )]
    SeriesKeyMismatch {
        table_name: String,
        existing: String,
    },

    #[error("catalog subscription error: {0}")]
    Subscription(#[from] SubscriptionError),

    #[error(transparent)]
    Other(#[from] anyhow::Error),

    #[error(
        "Cannot overwrite Processing Engine Trigger {} in Database {}",
        trigger_name,

View on GitHub (pinned to 06200ef96b)