Inconsistent error responses cause death-by-a-thousand-cuts on the frontend. If one endpoint returns a string, another returns nested objects, and a third throws HTML, you end up with messy UI conditionals everywhere. I use a small set of stable error codes and include a human-readable message only when it’s safe. For validation, I return a list of field issues. For unknown errors, I return a generic code and keep details in logs. I also include a request id so support can map a screenshot to server logs quickly. The point isn’t to over-design an error system; it’s to make it predictably boring so the UI can handle failures without special cases.