Budibase/budibase · error · HTTPError
err?.message || err (rethrown as HTTPError)
Error message
err?.message || err (rethrown as HTTPError)
What it means
The same create() catch block handles non-Error throwables (or Errors without message): it rethrows HTTPError(err?.message || err, err.status || 500). This branch fires when the thrown value is not an Error instance (e.g. a string thrown by a connector) or when err.message is undefined, defaulting to status 500.
Source
Thrown at packages/server/src/sdk/workspace/tables/external/index.ts:118
}
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)
}
}
}
export async function save(
datasourceId: string,
update: Table,
opts?: { tableId?: string; renaming?: RenameColumn }
) {
let tableToSave: TableRequest = {
...update,
type: "table",
_id: buildExternalTableId(datasourceId, update.name),
sourceId: datasourceId,
}
const tableId = opts?.tableId || update._id
let oldTable: Table | undefinedView on GitHub (pinned to a81a902e9a)
Solutions
- Inspect err.message in the resulting HTTPError for the raw thrown value
- Fix the connector/driver that throws non-Error values (throw new Error(...) instead)
- Check err.status on the HTTPError to distinguish 400 (client) from 500 (internal) responses
- Test the datasource connection directly to isolate driver misbehavior
Example fix
// before (in a connector)
throw "connection timed out"
// after
throw new Error("connection timed out") Defensive patterns
Strategy: try-catch
Validate before calling
// ensure connector calls only throw Error instances
if (typeof result === "undefined") throw new Error("Connector returned undefined") Type guard
function isErrorWithMessage(err: unknown): err is Error {
return err instanceof Error && typeof err.message === "string"
} Try / catch
try {
await tables.external.create(table)
} catch (err) {
const status = err instanceof HTTPError ? err.status : 500
const msg = err instanceof Error ? err.message : String(err)
console.error(`Table create failed (${status}):`, msg)
} Prevention
- Make custom connectors throw Error objects, not strings
- Handle both Error and non-Error throwables in wrappers
- Surface err.status to distinguish client vs server faults
When it happens
Trigger: A connector or plugin throws a non-Error value (string/object) during external table save, or an Error subclass lacking a message — caught at the same wrapper and converted to a 500 HTTPError.
Common situations: Custom SQL connectors throwing plain strings; undefined err.message from third-party datasource drivers; proxy/fetch failures throwing non-Error objects.
Related errors
- err.message (rethrown as HTTPError)
- err.message (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/d9abd53f3f5245a8.
Report an issue: GitHub.