๐ŸŒฌ๏ธ Breeze docs

Errors as values

A handler โ€” and a middleware โ€” returns an error. One function decides what that becomes on the wire, and a connection can never be left with no response at all.

router.Handle(breeze.GET, "/orders/:id", func(ctx *breeze.Context) error {
	order, err := store.Find(ctx.Param("id"))
	if errors.Is(err, sql.ErrNoRows) {
		return breeze.NewHTTPError(404, "no such order")
	}
	if err != nil {
		// client sees "unavailable"; the driver's message goes to the log only
		return breeze.WrapHTTPError(502, "the order service is unavailable", err)
	}
	return ctx.JSON(order)
})

What a returned error becomes

ReturnedResponse
*binding.ValidationError422 with field-level RFC 9457 detail
*breeze.HTTPErrorits status, with Message as the detail
anything elselogged to stderr, generic 500

Constructing an HTTPError

breeze.NewHTTPError(status int, message string) *HTTPError
breeze.WrapHTTPError(status int, message string, err error) *HTTPError

WrapHTTPError is for the case where the client-facing message and the underlying cause should not be the same string โ€” the wrapped error is logged, message is what the client sees. HTTPError.Unwrap() returns the wrapped error, so errors.Is / errors.As still work against it.

Why binding errors get their own status

A *binding.ValidationError becomes a 422, not a 400, because the request was syntactically valid and semantically wrong โ€” the distinction a client needs to decide whether to retry with different input or fix its serialization. Malformed JSON gets the 400. See Request Binding & Validation for the full error shape, which is RFC 9457 problem+json:

{
  "type": "about:blank",
  "status": 422,
  "title": "Validation Failed",
  "errors": [
    {"field": "Name",  "rule": "required", "message": "Name is required"},
    {"field": "Email", "rule": "email",    "message": "Email must be a valid email"}
  ]
}

The fallback case

Anything that is neither a *binding.ValidationError nor a *breeze.HTTPError is logged to stderr with the request context, and the client gets a generic 500 with no internal detail leaked onto the wire. This is the safe default: an unclassified error is assumed to carry information the caller should not see.

Generated documentation for the Breeze framework ยท built with SvelteKit, fully static.