laravel precognition validation inertia vue

Laravel Precog always returns success

brodenbrett

QA Engineer · 2024-01-08

Laravel Company

I'm using a fresh install of Laravel, Inertia, and Vue. Here is my set up: // routes/web.php use App\Http\Requests\EmailRequest; use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests; use Illuminate\Support\Facades\Route; Route::inertia('/', 'Welcome')->name('home'); Route::post('/', function (EmailRequest $request) { dd(request()->all(), request()->

Laravel Precognition is designed to let frontend frameworks validate input before submission, but in Inertia and Vue setups it often appears to always return success. The cause is almost always a mismatch between how the client serializes the request and how Precognition expects to consume the Precognition header. This post explains the contract between client and server, common pitfalls, and how to restore live validation feedback.

How Precognition Works

Precognition depends on the X-Precognition header added by the Inertia middleware. When your form handler detects a Precognitive request, it returns validation errors without executing the controller logic. If the header is missing or the request payload is not FormData or JSON in the expected shape, Precognition silently succeeds, and your frontend receives no error object to display.

Inertia and Vue Integration

Ensure you are importing and using laravel-precognition-vue-inertia on the frontend. The useForm helper reads Precognition responses and exposes the errors property reactively. A common mistake is calling form.post() with an empty data object so that the request body is omitted. Verify with network dev tools that the X-Precognition header is present on the prediction request and that the response status is 422 rather than 200.

Testing Precognitive Responses

Automated tests should assert that a Precognitive request returns a 422 status and that the response contains expected error keys. Use $this->withHeaders(['X-Precognition' => 'true']) when constructing the test request. This guards against future package upgrades that change middleware ordering.

Debugging Steps

First, check middleware order: HandlePrecognitiveRequests must run before authentication and validation middleware. Second, inspect the request payload in Tinker or a temporary log to confirm attribute names match your FormRequest rules. Third, make sure your Inertia form includes the :errors prop so Vue can render the failure state. Proper request lifecycle tests parallel the session behavior tests described in Database Session creates another record after logging out, which reinforces how Laravel test suites should validate request lifecycle behavior.

Conclusion

Precognition is a contract, not magic. Match the client serialization to the server expectation, confirm middleware order, and always test for 422 responses under Precognitive conditions.

Related Posts

These related posts cover test reliability, authentication flows, and frontend validation patterns in Laravel.

Why Precognition Might Bypass Validation

If you're using Inertia, confirm that your form is using the correct request method and URL. Precognition only fires on POST, PUT, PATCH, or DELETE requests with the Precognition header. A GET request or a form that submits via X-HTTP-Method-Override may bypass Precognition entirely. Also check that your Form Request's prepareForValidation() isn't merging precognition data in a way that nulls out required fields.

Another subtle issue: when using route model binding with implicit binding, the Form Request may resolve the model before validation runs during precognition, causing a model-not-found exception that gets converted to a validation error that your frontend ignores. Ensure your Inertia form's onError() handler is displaying validation messages properly.

Testing Precognition in Feature Tests

In Laravel tests, send a POST request with the Precognition header: $this->withHeaders(['Precognition' => 'true'])->postJson('/your-endpoint', $data)->assertOk(); If the response is 200 when you expect validation errors, your Form Request rules might not be applying. Ensure you're importing the correct Form Request class in your route or controller, and that no middleware is short-circuiting validation.

For debugging Laravel behavior more broadly, see Database Session creates another record after logging out and Upgrading from 13.6.1.

Inertia and Precognition Edge Cases

Inertia's useForm helper automatically handles Precognition, but only if you use it consistently across all form submissions. If you have mixed form handling (some via Inertia, some via vanilla Axios), ensure every manual submit sends the Precognition header. Also check that your Inertia middleware correctly transforms validation errors into the shape your frontend expects. Inertia expects errors as a plain object with field names as keys, not Laravel's default error bag array.

If you use Form Request classes with complex conditional rules, ensure that Precognition requests reach them. The HandlePrecognitiveRequests middleware is order-sensitive: it must run before other middleware that might modify or terminate the request. In your HTTP Kernel, keep it in the web middleware group near the top.

Testing Precognition with Pest or PHPUnit

Write a simple test to verify Precognition behavior: send a request with invalid data and the Precognition header, and assert the response contains the expected validation error structure. This test catches misconfigurations early. Include tests for the success path too: a Precognition request with valid data should return a 200 with no errors.

For related testing issues, see Database Session creates another record after logging out and Upgrading from 13.6.1.

How Laravel Precognition Works

Laravel Precognition allows you to validate incoming requests without persisting changes to the database. It's designed for Inertia.js applications where the frontend needs to validate form inputs before navigating away. The HandlePrecognitiveRequests middleware intercepts the request and returns validation errors without executing the controller logic.

If Precognition always returns success, the most likely issue is that the middleware is not registered or the request headers are not being set correctly. Inertia's useForm helper handles Precognition automatically, but manual AJAX requests need to include the Precognition header set to true. Verify with browser dev tools that the header is present.

Testing Precognition Manually

To test Precognition outside of Inertia, send a POST request with the Precognition: true header. Your Laravel application should respond with validation errors if present, or a 200 status with an empty body if validation passes. If you're always getting 200, your form request's rules() method may be returning empty or your validation is bypassed. Check that the request is actually reaching the Form Request and not being short-circuited by another middleware.

See Database Session creates another record after logging out for related Laravel testing behavior.

Related Posts