{"record":{"id":"b292e5f7835fd007","repo":"Budibase/budibase","slug":"external-tables-cannot-be-migrated","errorCode":null,"errorMessage":"External tables cannot be migrated","messagePattern":"External tables cannot be migrated","errorType":"validation","errorClass":"BadRequestError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/tables/migration.ts","lineNumber":106,"sourceCode":"    throw e\n  }\n}\n\ninterface ColumnMigrator {\n  doMigration(): Promise<MigrationResult>\n}\n\nfunction getColumnMigrator(\n  table: Table,\n  oldColumn: FieldSchema,\n  newColumn: FieldSchema\n): ColumnMigrator {\n  // For now, we're only supporting migrations of user relationships to user\n  // columns in internal tables. In the future, we may want to support other\n  // migrations but for now return an error if we aren't migrating a user\n  // relationship.\n  if (isExternalTableID(table._id!)) {\n    throw new BadRequestError(\"External tables cannot be migrated\")\n  }\n\n  if (!(oldColumn.name in table.schema)) {\n    throw new BadRequestError(`Column \"${oldColumn.name}\" does not exist`)\n  }\n\n  if (\n    newColumn.type !== FieldType.BB_REFERENCE_SINGLE &&\n    newColumn.type !== FieldType.BB_REFERENCE\n  ) {\n    throw new BadRequestError(`Column \"${newColumn.name}\" is not a user column`)\n  }\n\n  if (newColumn.subtype !== BBReferenceFieldSubType.USER) {\n    throw new BadRequestError(`Column \"${newColumn.name}\" is not a user column`)\n  }\n\n  if (!isRelationshipField(oldColumn)) {","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/tables/migration.ts#L88-L124","documentation":"Budibase table column migrations (converting a user relationship column to a user BB_REFERENCE column) are only supported for internal (CouchDB) tables. getColumnMigrator checks the table ID and throws this BadRequestError when the table belongs to an external datasource (SQL/REST etc.). The migration SDK simply cannot rewrite rows/links for external tables.","triggerScenarios":"Calling sdk.tables.migrate (or the migrate() API endpoint) with a table whose _id is an external table ID (contains a datasource prefix like datasources/...), i.e. a table backed by PostgreSQL/MySQL/REST rather than the internal database.","commonSituations":"Developers building automation or scripts that batch-convert relationship columns across all tables in an app without filtering out externally-connected tables; apps where the same schema code path serves internal and SQL tables.","solutions":["Only call migrate() on internal tables - filter with !isExternalTableID(table._id) before invoking","Convert the external table data to an internal Budibase table first, then migrate","If the column must change on an external table, alter it directly in the source database and update the datasource schema in Budibase instead of using the migration SDK"],"exampleFix":"// before\nawait sdk.tables.migrate(table, \"users\", \"userRef\")\n// after\nimport { isExternalTableID } from \"../../../integrations/utils\"\nif (!isExternalTableID(table._id!)) {\n  await sdk.tables.migrate(table, \"users\", \"userRef\")\n}","handlingStrategy":"validation","validationCode":"import { isExternalTableID } from \"../integrations/utils\"\nif (isExternalTableID(table._id!)) {\n  throw new Error(`Table ${table._id} is external; migration not supported`)\n}","typeGuard":"const isInternalTable = (t: Table): boolean =>\n  !!t._id && !isExternalTableID(t._id)","tryCatchPattern":null,"preventionTips":["Check table._id with isExternalTableID before any schema migration","Only surface the migration UI/action for internal tables in your app code"],"tags":["bad-request","external-table","migration","validation"],"backgroundTag":"external-table-migration-unsupported","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}