Dev.to WebDev 🛠 Dev 👁 0 📖 3 min read

Your API Errors Shouldn't Be a Guessing Game

Imagine you're building a frontend application and an API request fails. The backend returns: { "message": "Something went wrong" } Great. But what went wrong? Was it a validation error? A missing resource?

Imagine you're building a frontend application and an API request fails.

The backend returns:

{
  "message": "Something went wrong"
}

Great. But what went wrong?

Was it a validation error? A missing resource? A permission issue? Or something else?

Now the frontend has to guess what happened.

There's a better way to handle API errors, and it's already standardized.

The Problem With API Errors

Different APIs often return errors in different formats.

One endpoint returns:

{
  "error": "Invalid email"
}

Another returns:

{
  "message": "User not found",
  "code": 404
}

And another might accidentally expose an internal database error.

This makes frontend development harder because every endpoint needs different error-handling logic.

What if every API followed the same error structure?

Meet Problem Details

RFC 7807 introduced a standard format called Problem Details for HTTP APIs.

It was later replaced by RFC 9457, which is the current standard.

The idea is simple: return errors in a consistent, predictable format.

Here's an example:

{
  "type": "https://api.example.com/problems/insufficient-funds",
  "title": "Insufficient Funds",
  "status": 422,
  "detail": "Your balance is $40, but the total is $55.",
  "instance": "/checkouts/123"
}

Much better, right?

Every field has a purpose:

  • type: Identifies the kind of error.
  • title: A short description of the problem.
  • status: The HTTP status code.
  • detail: Explains what happened in this request.
  • instance: Identifies the specific occurrence of the problem.

The API should also return the appropriate HTTP status code and this content type:

Content-Type: application/problem+json

Now the frontend knows what kind of problem occurred without guessing from random messages.

What About Form Validation?

This is where it gets even more useful.

Imagine a registration form with invalid inputs.

Your API could return:

{
  "type": "https://api.example.com/problems/validation",
  "title": "Validation Failed",
  "status": 422,
  "errors": [
    {
      "field": "email",
      "message": "Invalid email address"
    },
    {
      "field": "password",
      "message": "Must contain at least 8 characters"
    }
  ]
}

The errors array is a custom extension, not a required field in the standard.

Now the frontend can display each error beside the correct input.

No need to parse random error strings.

Handling Errors in JavaScript

Here's a simple example using fetch:

const response = await fetch("/api/register", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify(formData)
});

if (!response.ok) {
  const problem = await response.json();

  if (problem.type === "https://api.example.com/problems/validation") {
    console.log(problem.errors);
  } else {
    console.error(problem.title);
  }
}

In a real application, you should also handle network failures and responses that don't contain valid JSON.

The important part is that your frontend can rely on documented error types instead of matching message strings.

A Few Things Worth Remembering

Using Problem Details doesn't automatically solve every error-handling problem.

You still need to follow a few good practices:

  • Never expose stack traces, SQL queries, or internal secrets.
  • Keep error types stable so frontend code doesn't break.
  • Use appropriate HTTP status codes.
  • Use safe, user-friendly messages where appropriate.
  • Add a request ID when useful for debugging and support.

For localization, frontend applications can map stable error types to translated messages instead of relying on English error descriptions.

Final Thoughts

A good API isn't just about returning successful responses.

It's also about explaining failures clearly.

RFC 9457 gives us a standard way to do that.

No random error structures. No guessing from message strings. Just predictable errors that both frontend and backend developers can understand.

And the best part?

You don't need a new library or framework to get started. Just a consistent error format.

How are you currently handling API errors in your projects?

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.