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

  1. Ensure the table passed to create/save includes its _id (fetch the table first via tables.get if updating)
  2. Set table.sourceId to the datasource ID explicitly when constructing external tables
  3. 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

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


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