Budibase/budibase · error · BadRequestError

Only user relationship migration columns is currently suppor

Error message

Only user relationship migration columns is currently supported

What it means

The migration API currently only converts relationship (FieldType.LINK) columns that point at the internal user metadata table into bb-reference user columns; any other column type or link target is rejected with this BadRequestError.

Source

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

  }

  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 = {
    name: newColumnName,
    type,
    subtype: BBReferenceFieldSubType.USER,
  }

  if (newColumn.type === FieldType.BB_REFERENCE) {
    newColumn.constraints = {
      type: "array",
    }

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Only call migrate on LINK columns whose tableId === InternalTable.USER_METADATA
  2. For other relationship-to-reference conversions, recreate the column as a bb-reference and re-link data manually
  3. Filter the schema before looping migrations: `col.type === FieldType.LINK && col.tableId === InternalTable.USER_METADATA`
  4. Wait for/extend the migration implementation if you need support for other link targets

Example fix

// before
for (const col of Object.values(table.schema)) {
  await sdk.tables.migration.migrate(table, col.name, col.name + 'Ref')
}
// after
for (const col of Object.values(table.schema)) {
  if (col.type === FieldType.LINK && col.tableId === InternalTable.USER_METADATA) {
    await sdk.tables.migration.migrate(table, col.name, col.name + 'Ref')
  }
}
Defensive patterns

Strategy: validation

Validate before calling

function isMigratableUserLink(col: FieldSchema | undefined): boolean {
  return !!col && col.type === FieldType.LINK &&
    (col as RelationshipFieldMetadata).tableId === InternalTable.USER_METADATA
}

Type guard

function isUserRelationshipColumn(col: FieldSchema | undefined): col is RelationshipFieldMetadata {
  return !!col && col.type === FieldType.LINK &&
    (col as RelationshipFieldMetadata).tableId === InternalTable.USER_METADATA
}

Try / catch

try {
  await sdk.tables.migration.migrate(table, oldName, newName)
} catch (e) {
  if (e.message.includes('Only user relationship migration')) {
    // migrate manually or restrict which columns you migrate
  }
}

Prevention

When it happens

Trigger: Calling migrate(table, oldColumnName, newColumnName) where the old column is not a LINK column, or is a link to a table other than InternalTable.USER_METADATA (e.g. a regular one-to-many relationship to a custom table).

Common situations: Attempting to migrate ordinary relationship columns to references; migrating links to non-user tables; calling the migration API generically across all link columns in a schema.

Related errors


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