createError()
Use createError() when you want to throw a structured BlypError instead of a plain Error.
It is the right fit when you need:
- an HTTP status attached to the failure
- user-facing fields such as
why,fix, andlink - consistent logging severity based on the status code
- a serializable payload for API responses
Basic example
import { createError } from "@blyp/core";
throw createError({
status: 402,
code: "PAYMENT_DECLINED",
message: "Payment failed",
why: "Card declined by issuer",
fix: "Try a different payment method",
link: "https://docs.example.com/payments/declined",
details: { paymentId: "pay_123" },
});What Blyp logs when the error is caught:
[ERROR] Payment failed
status=402 code=PAYMENT_DECLINED type=BlypErrorWhat the HTTP response body looks like:
{
"status": 402,
"code": "PAYMENT_DECLINED",
"message": "Payment failed",
"why": "Card declined by issuer",
"fix": "Try a different payment method",
"link": "https://docs.example.com/payments/declined",
"details": {
"paymentId": "pay_123"
}
}What it gives you
- a throwable
BlypError - a default message when you only provide
status - automatic log severity based on status code
.toJSON()for response serialization
Logging behavior
By default:
4xxerrors log aterror5xxerrors log atcritical
You can override or suppress that behavior.
const error = createError({
status: 404,
message: "User not found",
skipLogging: true,
});
return Response.json(error.toJSON(), { status: error.status });const error = createError({
status: 503,
message: "Primary database unavailable",
logLevel: "warning",
logger: request.blypLog,
});Common use cases
API validation failures
if (!body.email) {
throw createError({
status: 400,
code: "EMAIL_REQUIRED",
message: "Email is required",
fix: "Pass email in the request body",
});
}Permission checks
if (!session.isAdmin) {
throw createError({
status: 403,
code: "ADMIN_REQUIRED",
message: "You do not have access to this resource",
why: "The current session lacks the admin role",
});
}Wrapping downstream failures
try {
await payments.charge(input);
} catch (cause) {
throw createError({
status: 502,
code: "PAYMENTS_UPSTREAM_FAILED",
message: "Payment provider request failed",
why: "The upstream provider returned an unexpected failure",
details: { cause },
});
}Pair it with HTTP_CODES
If you repeat the same error shape in multiple places, promote it to a reusable preset with HTTP Codes instead of repeating createError() calls inline.
import { HTTP_CODES } from "@blyp/core";
const INVALID_COUPON = HTTP_CODES.BAD_REQUEST.extend({
code: "INVALID_COUPON",
message: "Coupon code is invalid",
why: "The supplied coupon does not exist or has expired",
fix: "Check the code or request a new promotion link",
});
throw INVALID_COUPON.create({
details: {
coupon: body.coupon,
},
});Use direct createError() calls for one-off failures, and HTTP_CODES.<STATUS>.extend(...) when the same error contract should be shared across handlers or services.