ToolJet/ToolJet · warning · Error

Duplicate column keys are not allowed

Error message

Duplicate column keys are not allowed

What it means

Thrown by Supabase plugin updateRows() when two column-field entries target the same column name. The duplicate check `columnNames.some((item, idx) => columnNames.indexOf(item) != idx)` detects any repeated name and throws 'Duplicate column keys are not allowed' before building the update payload, because the later value would silently overwrite the earlier one.

Source

Thrown at marketplace/plugins/supabase/lib/index.ts:128

    const { create_table_name, create_body } = queryOptions;
    if (!create_body) throw new Error('Body required to create rows in table');
    const res = await supabaseClient.from(create_table_name).insert(JSON.parse(create_body));
    return res;
  }

  async updateRows(queryOptions: QueryOptions, supabaseClient: SupabaseClientType): Promise<Response> {
    const { update_table_name, update_filters, update_column_fields } = queryOptions;
    if (!update_column_fields) throw new Error('No column(s) provided to update');

    const updateColumnValues: Column[] = Object.values(update_column_fields);
    if (!updateColumnValues.length) throw new Error('No column(s) provided to update');

    const columnNames: string[] = updateColumnValues.map((item) => item.column).filter((columnName) => !!columnName);
    if (!columnNames.length) throw new Error('Provide column(s) with valid data');

    const isDuplicate: boolean = columnNames.some((item, idx) => columnNames.indexOf(item) != idx);
    if (isDuplicate) {
      throw new Error('Duplicate column keys are not allowed');
    }
    const updateQuery = supabaseClient.from(update_table_name).select();
    if (update_filters) {
      const updateFiltersData: Filter[] = Object.values(update_filters);
      this.addQueryFilters(updateQuery, updateFiltersData);
    }
    const { data, error } = await updateQuery;
    if (error) throw new Error('Failed to fetch table rows to update');

    const columnsData: object = {};
    updateColumnValues.forEach((columnObj) => {
      columnsData[columnObj.column] = columnObj.value;
    });
    const updateQueryRes: object[] = data.map((data: object) => ({ ...data, ...columnsData }));
    const res = await supabaseClient.from(update_table_name).upsert(updateQueryRes).select();
    return res;
  }

View on GitHub (pinned to 20602a8e10)

Solutions

  1. Remove or merge duplicate column-field entries so each column name appears exactly once.
  2. Dedupe client-side, keeping the intended value, before calling run().
  3. When generating entries programmatically, key the object by column name to prevent repeats.

Example fix

// before
update_column_fields: {
  c1: { column: 'status', value: 'a' },
  c2: { column: 'status', value: 'b' }
}

// after
update_column_fields: { c1: { column: 'status', value: 'b' } }
Defensive patterns

Strategy: validation

Validate before calling

function ensureNoDuplicateColumns(qo) {
  if (qo.operation !== 'update_row') return;
  const names = Object.values(qo.update_column_fields || {}).map(c => c && c.column).filter(Boolean);
  const dupe = names.find((n, i) => names.indexOf(n) !== i);
  if (dupe) throw new Error(`Duplicate column keys are not allowed: ${dupe}`);
}
ensureNoDuplicateColumns(queryOptions);

Type guard

function columnNamesUnique(qo): boolean {
  if (qo.operation !== 'update_row') return true;
  const names = Object.values(qo.update_column_fields || {}).map(c => c && c.column).filter(Boolean);
  return names.every((n, i) => names.indexOf(n) === i);
}

Try / catch

try { await svc.run(src, qo, id); } catch (e) { if (/Duplicate column/.test(e.message)) { dedupeColumnFields(); return; } throw e; }

Prevention

When it happens

Trigger: update_column_fields contains two or more entries whose .column is identical, e.g. { c1: { column: 'status', value: 'a' }, c2: { column: 'status', value: 'b' } }.

Common situations: User added the same column twice by mistake; a duplicated control binding produced repeated column names; copy-paste of a column row without changing its target.

Related errors


AI-assisted analysis of ToolJet/ToolJet@20602a8e10 (2026-08-13). Data as JSON: /api/errors/2a2f7f9d7e75226a. Report an issue: GitHub.