influxdata/influxdb · error · Error::DuplicateColumnName

duplicate column name

Error message

duplicate column name: {column}

What it means

DuplicateColumnNameSnafu is raised by write_table_batch in mutable_batch_pb when decoding a WriteTableBatch protobuf: two adjacent columns in the batch share the same name. The decoder walks the column list with a 2-wide window and rejects any duplicate, because a table batch must have unique column names to build a valid MutableBatch. The duplicate name is embedded in the message.

Solutions

  1. Deduplicate columns by name in the client/producer before sending the WriteTableBatch
  2. Reject or log the payload upstream with the duplicated column name from the error message
  3. Add a producer-side schema check that tag and field names are distinct per line/row

Example fix

// before
batch.columns.push(col_timestamp);
batch.columns.push(col_timestamp); // duplicate
// after
let seen: HashSet<&str> = HashSet::new();
if !seen.insert(col_timestamp.column_name.as_str()) { /* skip or error */ }
batch.columns.push(col_timestamp);
Defensive patterns

Strategy: validation

Validate before calling

fn has_duplicate_columns(names: &[&str]) -> bool {
    names.iter().collect::<std::collections::HashSet<_>>().len() != names.len()
}
if has_duplicate_columns(&column_names) { /* reject batch before sending */ }

Try / catch

match write_table_batch(batch, table_batch) {
    Err(e) if e.to_string().starts_with("duplicate column name") => /* log offending name and reject payload */,
    other => other?,
}

Prevention

When it happens

Trigger: Calling write_table_batch (directly or via decode_database_batch / the write path's run) on a protobuf WriteTableBatch whose `columns` list contains two entries with an identical column_name.

Common situations: A producer bug appending the same column twice when building the LP/protobuf payload; merging two row entries without deduplicating fields; schema drift where a tag and field were given the same name.

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

Appendix: source

Thrown at core/mutable_batch_pb/src/decode.rs:100

    if to_insert == 0 {
        return Ok(());
    }

    // Verify columns are unique
    let mut columns: Vec<&str> = table_batch
        .columns
        .iter()
        .map(|c| c.column_name.as_str())
        .collect();
    columns.sort_unstable();

    let mut found_time = columns.first().is_some_and(|f| *f == TIME_COLUMN_NAME);

    // it would be nice to use `array_windows` here but alas, that's nightly-only
    for two_names in columns.windows(2) {
        let first = two_names[0];
        let second = two_names[1];
        ensure!(
            first != two_names[1],
            DuplicateColumnNameSnafu { column: first }
        );

        found_time |= second == TIME_COLUMN_NAME;
    }

    ensure!(found_time, MissingTimeSnafu);

    let mut writer = Writer::new(batch, to_insert);
    for column in &table_batch.columns {
        let influx_type = pb_column_type(column)?;
        let valid_mask = compute_valid_mask(&column.null_mask, to_insert);
        let valid_mask = valid_mask.as_deref();

        // Already verified has values
        let values = column.values.as_ref().unwrap();

View on GitHub (pinned to 06200ef96b)