Budibase/budibase · error · Error
${readableMessage}
Error message
${readableMessage} What it means
MySQL integration's internalQuery() wraps the callback-based mysql client in a promise and maps driver errors via getReadableErrorMessage(SourceName.MYSQL, err.errno). When errno matches a known MySQL error code, it throws a new Error with the readable message and attaches the original driver error as cause; otherwise it rethrows the original error untouched.
Source
Thrown at packages/server/src/integrations/mysql.ts:281
disableCoercion: false,
}
): Promise<any[] | any> {
try {
if (opts?.connect) {
await this.connect()
}
const baseBindings = query.bindings || []
const bindings = opts?.disableCoercion
? baseBindings
: bindingTypeCoerce(baseBindings)
this.log(query.sql, bindings)
// Node MySQL is callback based, so we must wrap our call in a promise
const response = await this.client!.query(query.sql, bindings)
return response[0]
} catch (err: any) {
let readableMessage = getReadableErrorMessage(SourceName.MYSQL, err.errno)
if (readableMessage) {
throw new Error(readableMessage, { cause: err })
} else {
throw err
}
} finally {
if (opts?.connect && this.client) {
await this.disconnect()
}
}
}
async buildSchema(
datasourceId: string,
entities: Record<string, Table>
): Promise<Schema> {
const tables: { [key: string]: Table } = {}
await this.connect()
try {View on GitHub (pinned to a81a902e9a)
Solutions
- Read the readableMessage — it is the mapped MySQL error (e.g. duplicate entry) — and fix the SQL or data
- For ER_DUP_ENTRY, deduplicate or use INSERT ... ON DUPLICATE KEY UPDATE / INSERT IGNORE
- For access-denied errors, verify credentials and grant privileges / allow the host
- Inspect error.cause for the full driver error including the raw errno and SQL state
Example fix
// before: duplicate key on re-insert
INSERT INTO users (email) VALUES ('a@example.com')
// after
INSERT INTO users (email) VALUES ('a@example.com') ON DUPLICATE KEY UPDATE email = VALUES(email) Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: ensure table exists before inserting
const tables = await ds.getTableNames?.() ?? []
if (!tables.includes(tableName)) {
throw new Error(`Table ${tableName} does not exist in MySQL database`)
} Type guard
function hasMysqlErrno(err: unknown): err is { errno: number; message: string } {
return typeof err === "object" && err !== null && typeof (err as any).errno === "number"
} Try / catch
try {
return await ds.query(sqlQuery)
} catch (err) {
const cause = (err as any).cause
if (cause?.errno === 1062) {
// duplicate entry: retry with a different key or upsert
} else if (cause?.errno === 1146) {
// missing table: fix schema
} else if (cause?.errno === 1045) {
// access denied: fix credentials
}
throw err
} Prevention
- Design unique keys and use ON DUPLICATE KEY UPDATE for idempotent inserts
- Verify MySQL credentials, privileges and host allowlist before deploying
- Use parameterized bindings to avoid syntax errors from interpolation
- Keep connections alive or reconnect after wait_timeout drops; inspect err.cause.errno for specifics
When it happens
Trigger: Any MySQL error during query.sql execution whose err.errno is in the mapping — classically ER_DUP_ENTRY (1062) duplicate key, ER_NO_SUCH_TABLE (1146), ER_ACCESS_DENIED_ERROR (1045), syntax errors (1064), and connection losses.
Common situations: Inserting a duplicate unique key; querying a table that doesn't exist or is in another database; wrong credentials or host not whitelisted for the MySQL user; malformed SQL from dynamic query building; connection dropped by wait_timeout.
Related errors
- ${readableMessage}
- Invalid import url
- Only HTTP(S) URLs are allowed for query import
- Import url must not contain credentials
- attempted to create a table without specifying the table to
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/aeb98431fd93d1b3.
Report an issue: GitHub.