Budibase/budibase · error · BadRequestError

Column "${oldColumnName}" does not exist on table "${table.n

Error message

Column "${oldColumnName}" does not exist on table "${table.name}"

What it means

migrate() looks up table.schema[oldColumnName]; if the source column doesn't exist, there is nothing to migrate, so a BadRequestError naming the column and table is thrown.

Source

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

  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}"`
    )
  }

  if (
    oldColumn.type !== FieldType.LINK ||
    oldColumn.tableId !== InternalTable.USER_METADATA
  ) {
    throw new BadRequestError(
      `Only user relationship migration columns is currently supported`
    )
  }

  const type =
    oldColumn.relationshipType === RelationshipType.ONE_TO_MANY
      ? FieldType.BB_REFERENCE_SINGLE
      : FieldType.BB_REFERENCE
  const newColumn: FieldSchema = {

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Verify oldColumnName exists: `oldColumnName in table.schema` before calling
  2. Re-fetch the latest table document — your copy may be stale
  3. Check whether the migration already ran and the old column was removed
  4. Confirm you're using the schema key, not a label/derived name

Example fix

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

Strategy: validation

Validate before calling

const freshTable = await sdk.tables.get(table._id!)
if (!(oldColumnName in freshTable.schema)) {
  throw new Error(`Column "${oldColumnName}" not found`)
}

Type guard

function columnExists(table: Table, name: string): boolean {
  return name in table.schema
}

Try / catch

try {
  await sdk.tables.migration.migrate(table, oldName, newName)
} catch (e) {
  if (e.message.includes('does not exist on table')) {
    // re-fetch table or check whether migration already completed
  }
}

Prevention

When it happens

Trigger: Calling migrate(table, oldColumnName, newColumnName) where oldColumnName is not a key in the passed table's schema — due to a typo, a stale table object, or the column already having been migrated/renamed.

Common situations: Re-running a completed migration (old column already removed); referencing the column by display name instead of schema key; table fetched before a concurrent rename.

Related errors


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