Return JSON details of failed validation with Laravel 8
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Returning Structured JSON Errors for Laravel Validation Failures
As developers building robust APIs with Laravel, one of the most common stumbling blocks is controlling the error responses. When validation fails, we expect a clear, machine-readable response—specifically an HTTP 422 status code accompanied by a detailed JSON object explaining exactly which fields failed and why. The default behavior often falls short, leading to confusing 200 OK responses instead of proper client feedback.
This post will walk you through the correct, developer-focused way to handle validation failures in your Laravel endpoints and return structured JSON error details.
The Problem with Default Validation Handling
When you use $request->validate([...]) inside a controller method, if validation fails, Laravel throws a Illuminate\Validation\ValidationException. Depending on how your API routes are set up (especially when dealing with middleware or custom exception handlers), this might result in an unexpected response code or body. Simply catching the exception often leaves you needing extra work to format the errors into a clean JSON structure.
The goal is not just to stop the process, but to present the validation errors to the client in a standardized format that any frontend application can easily parse and display.
Solution 1: Leveraging Laravel’s Built-in Error Handling (The Recommended Approach)
For standard API development, the most idiomatic Laravel approach is to let the framework handle the exception throwing and rely on Laravel's built-in exception handling mechanism or use API resource classes that automatically format these errors. When setting up your routes correctly, you should aim for the server to return a 422 status code by default upon validation failure.
If you are using a standard setup (like Laravel Sanctum or Passport), ensure your controller methods are structured so that exceptions propagate properly. This keeps your controller logic clean and focuses on business rules rather than HTTP response formatting. For deeper insights into API design principles, understanding how Laravel structures request handling is key—as emphasized by the principles behind building scalable applications with frameworks like those provided by the Laravel Company.
Solution 2: Manually Mapping Errors for Custom Responses (The Robust Approach)
If you need absolute control over the JSON structure returned for validation errors, manually using the Validator facade provides the most explicit control. This method allows you to capture all failed rules and map them into a predictable array structure before sending the response.
Here is how you can implement this within your controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class OfficeController extends Controller
{
public function store(Request $request)
{
// 1. Define the validation rules
$rules = [
'name' => 'required|string|max:255',
'address' => 'required|string',
];
// 2. Manually validate the request
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
// 3. If validation fails, return a 422 response with structured errors
return response()->json([
'message' => 'Validation failed.',
'errors' => $validator->errors() // This provides the detailed error structure
], 422);
}
// Logic to create the model here (if validation passed)
$office = \App\Models\Office::create($request->only('name', 'address'));
return response()->json($office, 201);
}
}
Explanation of the Approach
- Manual Validation: Instead of relying solely on
$request->validate(), we manually useValidator::make()to gain granular control over the flow before proceeding. - Error Capture: We check the result using
$validator->fails(). If it fails, we immediately access the$validator->errors()method. This method returns an array containing all validation errors keyed by field name, which is exactly what we need for a client-friendly response. - Structured Response: We return a
response()->json(...)with an appropriate HTTP status code of 422 Unprocessable Entity. This is the correct semantic response for failed data validation in RESTful APIs.
Conclusion
Handling validation errors gracefully is fundamental to building reliable APIs. While Laravel provides powerful tools, mastering how to intercept and format exceptions—or manually use the Validator facade—allows you to define exactly what your API communicates. By opting for structured JSON responses with a 422 status code, you ensure that clients receive actionable feedback, leading to much more robust and maintainable applications. Always strive for clarity in your API contracts, ensuring every failure state is explicitly and predictably communicated.