Budibase/budibase · error · BadRequestError

Column "${oldColumn.name}" is not a user relationship

Error message

Column "${oldColumn.name}" is not a user relationship

What it means

The source column of a user migration must be a relationship (LINK) column. getColumnMigrator uses the isRelationshipField type guard and throws this BadRequestError when oldColumn is not a RelationshipFieldMetadata, i.e. it's a plain field (string, number, bb reference, etc.).

Source

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

  }

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

  if (
    newColumn.type !== FieldType.BB_REFERENCE_SINGLE &&
    newColumn.type !== FieldType.BB_REFERENCE
  ) {
    throw new BadRequestError(`Column "${newColumn.name}" is not a user column`)
  }

  if (newColumn.subtype !== BBReferenceFieldSubType.USER) {
    throw new BadRequestError(`Column "${newColumn.name}" is not a user column`)
  }

  if (!isRelationshipField(oldColumn)) {
    throw new BadRequestError(
      `Column "${oldColumn.name}" is not a user relationship`
    )
  }

  if (oldColumn.tableId !== InternalTable.USER_METADATA) {
    throw new BadRequestError(
      `Column "${oldColumn.name}" is not a user relationship`
    )
  }

  if (oldColumn.relationshipType === RelationshipType.ONE_TO_MANY) {
    if (newColumn.type !== FieldType.BB_REFERENCE_SINGLE) {
      throw new BadRequestError(
        `Column "${oldColumn.name}" is a one-to-many column but "${newColumn.name}" is not a single user column`
      )
    }
    return new SingleUserColumnMigrator(table, oldColumn, newColumn)
  }

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Only pass columns where oldColumn.type === FieldType.LINK to the migrator
  2. Filter the table schema: pick entries where isRelationshipField(col) is true
  3. If the data lives in a non-link column, a custom data import is needed - the migrator only converts relationships

Example fix

// before
await migrate(table, "ownerName", "owner")
// after
const col = table.schema["ownerName"]
if (col?.type === FieldType.LINK) await migrate(table, "ownerName", "owner")
Defensive patterns

Strategy: type-guard

Validate before calling

if (!isRelationshipField(oldColumn)) {
  throw new Error(`${oldColumn.name} is not a link column`)
}

Type guard

const isMigratableSource = (c: FieldSchema): c is RelationshipFieldMetadata =>
  isRelationshipField(c)

Prevention

When it happens

Trigger: Calling the migrator with an oldColumn whose type is not FieldType.LINK - e.g. trying to "migrate" a text or lookup column into a user column.

Common situations: Scripts iterating all columns of a table without filtering to type "link"; misunderstanding that only relationship-to-user-column migrations are supported.

Related errors


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