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
- Inspect the existing table schema (SHOW or the catalog) and align your writes so tag columns exactly match the existing series key.
- Fix the type of conflicting data on the client side (cast the value to the existing column's InfluxColumnType) before writing.
- 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.
- 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
- Freeze the tag set per measurement and version it alongside your writer code
- Validate line protocol tags against the table schema in CI before deploying writers
- Never send field data as tags after a table exists
- Use distinct measurement names when restructuring tags instead of mutating an existing table
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
- error from table buffer
- table not found in db
- {0}
- ' ' is a reserved column
- At least one field is required
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)