Budibase/budibase · error

err.message

Error message

err.message

What it means

This is the global Koa error-handling middleware in backend-core. It doesn't throw its own error; it catches everything downstream, derives status from err.status || err.statusCode || 500, logs (warn for 4xx, error for 5xx), and serializes { message: err.message, status } as the API error response body. The observed message "err.message" simply means the original thrown error's message is being surfaced to the client verbatim.

Source

Thrown at packages/backend-core/src/middleware/errorHandling.ts:15

import { APIError } from "@budibase/types"
import * as errors from "../errors"
import environment from "../environment"
import { stringContainsSecret } from "../security/secrets"
import { ParameterizedContext, Next } from "koa"

export async function errorHandling(ctx: ParameterizedContext, next: Next) {
  try {
    await next()
  } catch (err: any) {
    const status = err.status || err.statusCode || 500
    ctx.status = status

    if (status >= 400 && status < 500) {
      console.warn(err)
    } else {
      console.error("Got 5xx response code", err)
    }

    let error: APIError = {
      message: err.message,
      status,
      validationErrors: err.validation,
      error: errors.getPublicError(err),
    }

    if (stringContainsSecret(JSON.stringify(error))) {
      error = {
        message: "Unexpected error",
        status,
        error: "Unexpected error",
      }
    }

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Read the message in the response body — it identifies the actual failing operation; check server logs (console.warn/error) for the full stack
  2. Throw HTTPError with an explicit status in application code so clients get meaningful 4xx codes instead of 500
  3. Wrap low-level DB/HTTP errors in domain errors before they reach middleware
  4. For 5xx, check downstream services (database, SMTP, external APIs) indicated by the message

Example fix

// before
throw new Error("connection refused")
// after
throw new HTTPError("Database unavailable, please try again later", 503)
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try {
  await api.request(...)
} catch (e) {
  const status = e.status || e.statusCode || 500
  if (status >= 500) {
    // retry or check server logs for the full stack
  } else {
    // surface e.message to the user
  }
}

Prevention

When it happens

Trigger: Any middleware or controller throwing an Error/HTTPError: the client receives the error's message field with status err.status/err.statusCode, defaulting to 500 when neither is set.

Common situations: Seeing a raw internal error message (e.g. a Postgres/CouchDB error string) in an API response because a low-level error was thrown without a status; debugging why a 500 response carries an unexpected message; unhandled promise rejections inside route handlers.

Related errors


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