Budibase/budibase · error · Error

Column(s) "${duplicateColumn.join(", ")}" are duplicated - c

Error message

Column(s) "${duplicateColumn.join(", ")}" are duplicated - check for other columns with these name (case in-sensitive)

What it means

Internal tables store column names case-insensitively (SQLite keys are lowercased), so save() runs findDuplicateInternalColumns and rejects a schema where two columns differ only by case. The duplicated names are listed in the message.

Source

Thrown at packages/server/src/sdk/workspace/tables/internal/index.ts:94

  }
) {
  const db = context.getWorkspaceDB()

  // if the table obj had an _id then it will have been retrieved
  let oldTable: Table | undefined
  if (opts?.tableId) {
    oldTable = await getTable(opts.tableId)
  }

  // check all types are correct
  if (hasTypeChanged(table, oldTable)) {
    throw new Error("A column type has changed.")
  }

  // check for case sensitivity - we don't want to allow duplicated columns
  const duplicateColumn = findDuplicateInternalColumns(table)
  if (duplicateColumn.length) {
    throw new Error(
      `Column(s) "${duplicateColumn.join(
        ", "
      )}" are duplicated - check for other columns with these name (case in-sensitive)`
    )
  }

  // check that subtypes have been maintained
  table = checkAutoColumns(table, oldTable)

  // saving a table is a complex operation, involving many different steps, this
  // has been broken out into a utility to make it more obvious/easier to manipulate
  const tableSaveFunctions = new TableSaveFunctions({
    userId: opts?.userId,
    oldTable,
    importRows: opts?.rowsToImport,
  })
  table = await tableSaveFunctions.before(table)

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Rename one of the duplicated columns so all names are unique case-insensitively
  2. Normalize incoming import headers to lowercase before creating columns
  3. Check the listed names in the message and remove the redundant column
  4. Deduplicate schema keys programmatically before calling save

Example fix

// before
schema: { Email: {...}, email: {...} }
// after
schema: { email: {...} }
Defensive patterns

Strategy: validation

Validate before calling

function findCaseDuplicates(schema: Table['schema']): string[] {
  const seen = new Set<string>()
  const dups = new Set<string>()
  for (const name of Object.keys(schema)) {
    const lc = name.toLowerCase()
    if (seen.has(lc)) dups.add(name)
    seen.add(lc)
  }
  return [...dups]
}

Try / catch

try {
  await sdk.tables.saveTable(table)
} catch (e) {
  if (e.message.includes('are duplicated')) {
    // parse names from message and rename/remove one of them
  }
}

Prevention

When it happens

Trigger: Saving a table whose schema contains e.g. 'Email' and 'email', or any two columns that collide after case-insensitive normalization, via sdk.tables.saveTable/save().

Common situations: Importing CSVs/Excel sheets with headers differing only in case; merging schemas from two tables; programmatic schema generation that doesn't dedupe.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/f625c39d98c701f2. Report an issue: GitHub.