Budibase/budibase · error · Error
No table ID supplied
Error message
No table ID supplied
What it means
getDatasourceId resolves the datasource ID from a table for external (SQL) datasources. It uses table.sourceId if present, otherwise derives the datasource ID by parsing the table's _id via breakExternalTableId. If the table has neither a sourceId nor an _id, there is no way to identify the datasource, so it throws.
Source
Thrown at packages/server/src/sdk/workspace/tables/external/index.ts:102
if (oldColumn && column.timeOnly !== oldColumn.timeOnly) {
throw new Error(
`Column "${key}" can not change from time to datetime or viceversa.`
)
}
}
}
}
function getDatasourceId(table: Table) {
if (!table) {
throw new Error("No table supplied")
}
if (table.sourceId) {
return table.sourceId
}
if (!table._id) {
throw new Error("No table ID supplied")
}
return breakExternalTableId(table._id).datasourceId
}
export async function create(table: WithoutDocMetadata<Table>) {
const datasourceId = getDatasourceId(table)
const tableToCreate = { ...table, created: true }
try {
const result = await save(datasourceId!, tableToCreate)
return result.table
} catch (err: any) {
if (err instanceof Error) {
throw new HTTPError(err.message, 400)
} else {
throw new HTTPError(err?.message || err, err.status || 500)
}
}View on GitHub (pinned to a81a902e9a)
Solutions
- Ensure the table passed to create/save includes its _id (fetch the table first via tables.get if updating)
- Set table.sourceId to the datasource ID explicitly when constructing external tables
- Only call save/create with tables loaded through the SDK getters, which populate _id and sourceId
Example fix
// before
await tables.external.create({ name: "users", schema, primary: ["id"] })
// after
const dsTable = await tables.external.get(datasourceId, "users")
dsTable.schema.newColumn = fieldSchema
await tables.external.create(dsTable) Defensive patterns
Strategy: validation
Validate before calling
if (!table.sourceId && !table._id) throw new Error("Table requires _id or sourceId before save") Type guard
function hasTableIdentifier(table: Table): table is Table & ({ _id: string } | { sourceId: string }) {
return typeof table.sourceId === "string" || typeof table._id === "string"
} Try / catch
try {
await tables.external.create(table)
} catch (err) {
if (err.message === "No table ID supplied") {
// re-fetch table by name to get _id, then retry
}
} Prevention
- Always load external tables via SDK getters before mutating and saving
- Set sourceId explicitly when constructing external table objects
- Never save hand-built table objects without an _id
When it happens
Trigger: Calling getDatasourceId(table) (directly or via create/save of an external table) with a table object that has no sourceId and no _id — e.g. a newly constructed table object not yet persisted, or a partially hydrated table from an API response.
Common situations: Building a new external table without first persisting it; passing a table-like object from a client request that omitted _id; deserialization dropping metadata fields (_id) from the table document.
Related errors
- Error getting status
- Unable to remove doc without a valid _id and _rev.
- Cannot store document without _id field.
- Configuration invalid. Must contain google clientID and clie
- Configuration invalid. Must contain clientID, clientSecret,
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/c135e00fc2a8be65.
Report an issue: GitHub.