Budibase/budibase · warning · HTTPError
Cannot duplicate external tables
Error message
Cannot duplicate external tables
What it means
Table duplication is only supported for internal (CouchDB) tables. The duplicate endpoint explicitly rejects external tables (backed by SQL/REST datasources) with HTTP 422 because rows cannot be cloned through the external connector in the same way.
Source
Thrown at packages/server/src/api/controllers/table/index.ts:326
let tableId = ctx.params.tableId as string
const table = await sdk.tables.getTable(tableId)
let result = await sdk.tables.migrate(table, oldColumn, newColumn)
for (let table of result.tablesUpdated) {
builderSocket?.emitTableUpdate(ctx, table, {
includeOriginator: true,
})
}
ctx.body = { message: `Column ${oldColumn} migrated.` }
}
export async function duplicate(ctx: UserCtx<void, SaveTableResponse>) {
const tableId = ctx.params.tableId as string
const table = await sdk.tables.getTable(tableId)
if (isExternalTable(table)) {
throw new HTTPError("Cannot duplicate external tables", 422)
}
const duplicatedTable = await sdk.tables.duplicate(table, ctx.user._id)
ctx.message = `Table ${table.name} duplicated successfully.`
ctx.body = duplicatedTable
const processedTable = await processTable(duplicatedTable)
builderSocket?.emitTableUpdate(ctx, cloneDeep(processedTable))
}
export async function publish(
ctx: UserCtx<PublishTableRequest, PublishTableResponse>
) {
const tableId = ctx.params.tableId as string
const table = await sdk.tables.getTable(tableId)
if (!table) {View on GitHub (pinned to a81a902e9a)
Solutions
- Duplicate the table inside the source database directly and re-sync the datasource in Budibase
- Create a new internal table and copy data via a Budibase automation/script
- Use a query against the external datasource that performs the copy (e.g. SQL CREATE TABLE ... AS SELECT)
Defensive patterns
Strategy: type-guard
Validate before calling
async function canDuplicate(tableId, api) {
const table = await api.getTable(tableId)
return table && table.source !== "external" && table.type !== "external"
} Type guard
const isInternalTable = (t) => Boolean(t) && !t.sourceId && t.source !== "external"
Try / catch
try {
await api.duplicateTable(tableId)
} catch (e) {
if (e?.status === 422 && /Cannot duplicate external tables/.test(e.message)) {
// fall back to copying data into a new internal table via script/automation
} else throw e
} Prevention
- Filter table lists by datasource type before bulk duplication
- Educate users that SQL/REST tables cannot be duplicated in-app
- Perform duplication at the database layer for external tables
- Gate duplicate actions in custom UIs on datasource type
When it happens
Trigger: POST to the table duplicate endpoint (/tables/:tableId/duplicate) where tableId resolves to a table whose datasource is external (isExternalTable true), e.g. a PostgreSQL/MySQL/REST datasource table.
Common situations: Users attempting to duplicate SQL-backed tables from the Builder data section; scripts iterating all tables and duplicating each without filtering by datasource type.
Related errors
- Table ID is unknown, cannot find table
- Cannot fetch row by ID "${rowId}"
- Unable to lookup relationships - undefined column properties
- unable to find related table
- Cannot make field "${key}" required, it has a default value.
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/2fa71f4a4e4a3fb0.
Report an issue: GitHub.