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
- Read err.message on the HTTPError to identify the underlying save failure
- Validate the table payload (unique name, valid column types, primary field) before create
- Check CouchDB/DB health if writes are failing infrastructure-side
- 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
- Validate table payload (name uniqueness, column types) before create
- Check CouchDB health when writes fail repeatedly
- Use SDK builders/utilities to construct well-formed table objects
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
- err.message (rethrown as HTTPError)
- err?.message || err (rethrown as HTTPError)
- Invalid license key
- License key has already been activated
- Error activating license key: ${message}
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/223abae10d0560e1.
Report an issue: GitHub.