If every appliance in a kitchen used its own private signal for 'something's wrong' — one blinks a light, one beeps, one shows a code only its own manual explains — you'd need a different mental model per appliance just to notice a failure. A single shared warning light across every appliance means you only need to learn what trouble looks like once. A consistent error envelope does the same job for an API: whichever endpoint fails, the shape of the failure looks the same.
Every payment gateway and shipping carrier I integrated into Magento at Infracommerce failed in its own way — different HTTP codes, different error bodies, some just an opaque string. Magento's checkout couldn't show a different error UI per integration, so wiring in a new gateway always meant translating whatever it threw back into the shape the rest of checkout already expected. That's the same discipline a consistent API error envelope enforces: a caller shouldn't need a special case per endpoint just to know what went wrong.
Trade-off: normalizing every gateway's error into one shape means translating away some of the original detail — the exact Stripe or PayPal error code is still worth logging somewhere, even if the caller-facing response only ever sees the generic shape.
Before
// Gateway A throws a string, Gateway B a numeric code,
// Gateway C its own exception shape —
// checkout has to know all three
try {
$this->gateway->charge($amount);
} catch (StripeException|PaypalError|KlarnaFault $e) {
return response()->json(['error' => $e->getMessage()], 500);
}After
class ApiExceptionHandler
{
public function render(Throwable $e): JsonResponse
{
$status = $e instanceof ValidationException ? 422 : 500;
return response()->json([
'error' => ['code' => $status, 'message' => $e->getMessage()],
], $status);
}
}
// every endpoint's failure now shares the same {error: {code, message}} shape