Budibase/budibase · error · HTTPError

Column "${table.primaryDisplay}" cannot be used as a display

Error message

Column "${table.primaryDisplay}" cannot be used as a display type.

What it means

A table's primaryDisplay must reference a column that exists and is eligible as a display column. guardTable rejects saves where primaryDisplay points at an invalid column, but only when the table is newly created or the primaryDisplay value is actually changing — to avoid breaking legacy misconfigured tables.

Source

Thrown at packages/server/src/api/controllers/table/index.ts:126

    }, {})
    return Object.keys(updates).length ? { ...row, ...updates } : row
  })
}

async function guardTable(table: Table, isCreate: boolean) {
  checkDefaultFields(table)

  if (
    table.primaryDisplay &&
    !canBeDisplayColumn(table.schema[table.primaryDisplay]?.type)
  ) {
    // Prevent throwing errors from existing badly configured tables. Only throw for new tables or if this setting is being updated
    if (
      isCreate ||
      (await sdk.tables.getTable(table._id!)).primaryDisplay !==
        table.primaryDisplay
    ) {
      throw new HTTPError(
        `Column "${table.primaryDisplay}" cannot be used as a display type.`,
        400
      )
    }
  }
}

// covers both internal and external
export async function fetch(ctx: UserCtx<void, FetchTablesResponse>) {
  const internal = await sdk.tables.getAllInternalTables()

  const datasources = await sdk.datasources.getExternalDatasources()

  const external: Table[] = []
  for (const datasource of datasources) {
    let entities = datasource.entities
    if (entities) {
      for (const entity of Object.values(entities)) {

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Set primaryDisplay to an existing schema column name (exact key from table.schema)
  2. Fetch the table first (GET /tables/:id) and copy a valid schema key into primaryDisplay
  3. If the old table already has a bad primaryDisplay, fix it via a save that changes the value once — the guard only throws on create/change

Example fix

// before
await api.post('/tables', { name: "Customers", primaryDisplay: "fullName", schema: { name: {...} } })
// after
await api.post('/tables', { name: "Customers", primaryDisplay: "name", schema: { name: {...} } })
Defensive patterns

Strategy: validation

Validate before calling

function isDisplayCandidate(table, col) {
  const field = table.schema?.[col]
  return Boolean(field) && !"link".includes(field.type) && col !== table._id
}
const current = await api.getTable(id).catch(() => null)
if ((!current || current.primaryDisplay !== table.primaryDisplay) && !isDisplayCandidate(table, table.primaryDisplay)) {
  throw new Error("primaryDisplay must be an existing schema column")
}

Type guard

const validDisplay = (t, col) => Object.prototype.hasOwnProperty.call(t?.schema || {}, col)

Try / catch

try {
  await api.saveTable(table)
} catch (e) {
  if (e?.status === 400 && /cannot be used as a display type/.test(e.message)) {
    const firstCol = Object.keys(table.schema)[0]
    // retry with a known-valid column as primaryDisplay
  } else throw e
}

Prevention

When it happens

Trigger: Creating a table with primaryDisplay set to a nonexistent/ineligible column, or updating an existing table's primaryDisplay to such a column (compared against the stored table's current primaryDisplay via sdk.tables.getTable).

Common situations: API scripts setting primaryDisplay to a field name that was renamed or deleted; picking an auto-column or unsupported type as display; importing table JSON from another app with different columns.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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