Budibase/budibase · error · BadRequestError

Column "${newColumnName}" already exists

Error message

Column "${newColumnName}" already exists

What it means

migrate() (user relationship column migration) first checks that the target column name is not already present in table.schema; if it is, the migration would overwrite an existing column, so a BadRequestError is thrown.

Source

Thrown at packages/server/src/sdk/workspace/tables/migration.ts:33

  Row,
  Table,
} from "@budibase/types"
import { cloneDeep } from "lodash"
import sdk from "../.."
import { EventType, updateLinks } from "../../../db/linkedRows"
import { isExternalTableID } from "../../../integrations/utils"

export interface MigrationResult {
  tablesUpdated: Table[]
}

export async function migrate(
  table: Table,
  oldColumnName: string,
  newColumnName: string
): Promise<MigrationResult> {
  if (newColumnName in table.schema) {
    throw new BadRequestError(`Column "${newColumnName}" already exists`)
  }

  if (newColumnName === "") {
    throw new BadRequestError(`Column name cannot be empty`)
  }

  if (isInternalColumnName(newColumnName)) {
    throw new BadRequestError(`Column name cannot be a reserved column name`)
  }

  const oldColumn = table.schema[oldColumnName]

  if (!oldColumn) {
    throw new BadRequestError(
      `Column "${oldColumnName}" does not exist on table "${table.name}"`
    )
  }

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Choose a different newColumnName that doesn't exist in the schema
  2. Check `newColumnName in table.schema` before calling and handle gracefully
  3. If the migration partially ran, clean up or resume from the already-created column rather than re-running
  4. Verify the table document is current (re-fetch) — stale table objects may miss a recently added column

Example fix

// before
await sdk.tables.migration.migrate(table, 'user', 'owner')
// after
if (!('owner' in table.schema)) {
  await sdk.tables.migration.migrate(table, 'user', 'owner')
}
Defensive patterns

Strategy: validation

Validate before calling

if (newColumnName in table.schema) {
  throw new Error(`Pick a different name; "${newColumnName}" exists`)
}

Try / catch

try {
  await sdk.tables.migration.migrate(table, oldName, newName)
} catch (e) {
  if (e.message.includes('already exists')) {
    // choose another name or resume the partial migration
  }
}

Prevention

When it happens

Trigger: Calling sdk.tables.migration.migrate(table, oldColumnName, newColumnName) where newColumnName already exists as a key in the table's schema (case-sensitive check).

Common situations: Retrying a partially-completed migration that already added the new column; picking a name that collides with another field; UI letting users type an existing field name.

Related errors


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