Budibase/budibase · error · HTTPError

err.message (rethrown as HTTPError)

Error message

err.message (rethrown as HTTPError)

What it means

The internal table create path wraps table persistence: any Error thrown while saving the table document (validation, dupes, DB errors) is rethrown as HTTPError(err.message, 400); non-Error throwables get status 500. This normalizes internal table save failures into API errors.

Source

Thrown at packages/server/src/sdk/workspace/tables/internal/index.ts:61

  }

  const isImport = !!rows

  if (!tableToSave.views) {
    tableToSave.views = {}
  }

  try {
    const { table } = await save(tableToSave, {
      userId,
      rowsToImport: rows,
      isImport,
    })

    return table
  } catch (err: any) {
    if (err instanceof Error) {
      throw new HTTPError(err.message, 400)
    } else {
      throw new HTTPError(err.message || err, err.status || 500)
    }
  }
}

export async function save(
  table: Table,
  opts?: {
    userId?: string
    tableId?: string
    rowsToImport?: Row[]
    renaming?: RenameColumn
    isImport?: boolean
  }
) {
  const db = context.getWorkspaceDB()

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Read err.message on the HTTPError to identify the underlying save failure
  2. Validate the table payload (unique name, valid column types, primary field) before create
  3. Check CouchDB/DB health if writes are failing infrastructure-side
  4. Log and fix the source that throws non-Error values if you see 500s

Example fix

// before
await tables.internal.create(malformedTable) // HTTPError 400
// after
try {
  await tables.internal.create(malformedTable)
} catch (err) {
  // err.status === 400, err.message describes the save failure
  console.error("Internal table create failed:", err.message)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!table.name) throw new Error("Table name required")
for (const col of Object.keys(table.schema || {})) {
  if (!table.schema[col].type) throw new Error(`Column ${col} missing type`)
}

Type guard

function isHTTPError(err: unknown): err is HTTPError {
  return err instanceof HTTPError
}

Try / catch

try {
  await tables.internal.create(table)
} catch (err) {
  if (err instanceof HTTPError && err.status === 400) {
    console.error("Internal table save failed:", err.message)
  } else {
    throw err
  }
}

Prevention

When it happens

Trigger: Calling tables.internal.create() (table save on internal Budibase DB) when the underlying save throws — invalid schema, name conflicts, CouchDB write failures — surfaced as HTTPError 400 (or 500 for non-Error throws).

Common situations: Duplicate table names or column name conflicts; invalid column type definitions; CouchDB connectivity/write failures; automation or import code constructing malformed table payloads.

Related errors


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