influxdata/influxdb · critical

schema contains repeated column name

Error message

schema contains repeated column name

What it means

In MutableBatch::try_into_arrow's conversion loop, the first occurrence of a field name consumes its column via std::mem::take (leaving None); a second schema field with the same name then finds None and panics with 'schema contains repeated column name'. Arrow schemas permit duplicate field names, so a projection or schema listing the same column twice triggers this.

Source

Thrown at core/mutable_batch/src/lib.rs:133

        let Self {
            column_names,
            columns,
            row_count: _,
        } = self;

        // Convert to Vec<Option<_>> to remove each Column avoid copying the
        // underlying data
        let mut columns = columns.into_iter().map(Some).collect::<Vec<_>>();

        let arrays: Result<Vec<_>, Error> = schema
            .iter()
            .map(|(_, field)| {
                let column_index = column_names
                    .get(field.name())
                    .expect("schema contains non-existent or column");
                std::mem::take(&mut columns[*column_index])
                    .expect("schema contains repeated column name")
                    .try_into_arrow()
                    .context(ColumnSnafu {
                        column: field.name(),
                    })
            })
            .collect();

        RecordBatch::try_new(schema.into(), arrays?).context(ArrowSnafu {})
    }

    /// Returns an iterator over the columns in this batch in no particular order
    pub fn columns(&self) -> impl ExactSizeIterator<Item = (usize, &String, &Column)> + '_ {
        self.column_names
            .iter()
            .map(move |(name, idx)| (*idx, name, &self.columns[*idx]))
    }

    /// Yield an iterator of column `(name, type)` tuples for all columns in

View on GitHub (pinned to d28e26e048)

Solutions

  1. Deduplicate projection names before calling try_into_arrow (e.g. collect into a BTreeSet/IndexSet)
  2. Fix the schema construction that produced duplicate field names
  3. Assert uniqueness up front: assert_eq!(names.len(), dedup(names).len()) in tests around projection-building code

Example fix

// before
let cols = ["time", "cpu", "cpu"];  // duplicate
let rb = batch.try_into_arrow(Projection::Some(&cols))?;

// after
let cols: Vec<_> = cols.into_iter().collect::<std::collections::BTreeSet<_>>().into_iter().collect();
let rb = batch.try_into_arrow(Projection::Some(&cols))?;
Defensive patterns

Strategy: validation

Validate before calling

// dedupe projection names before use
let deduped: Vec<&str> = {
    let seen: std::collections::BTreeSet<&str> = projection.iter().copied().collect();
    seen.into_iter().collect()
};
assert_eq!(deduped.len(), projection.len(), "duplicate column names in projection");

Prevention

When it happens

Trigger: Passing Projection::Some with the same column name repeated; a schema built by concatenating two table schemas that both contain an identically named column; de-duplication lost during a merge.

Common situations: Programmatic projection construction from multiple sources without dedupe; wildcard 'SELECT *' plus explicit column names producing a duplicated list; schema merge during table evolution.

Related errors


AI-assisted analysis of influxdata/influxdb@d28e26e048 (2026-08-16). Data as JSON: /api/errors/46870be31159233e. Report an issue: GitHub.