Table of Contents
Laravel 8 min read

Laravel Precog Always Returns Success: Troubleshooting Guide

Debug why Laravel Precog's HandlePrecognitiveRequests middleware always returns success. Common causes and fixes for precognitive request validation.

2026-06-29 laravel precog, validation, debugging, precognitive requests

Laravel Precognition is a powerful feature that lets you validate forms before the user submits them, providing real-time validation feedback. But a common issue reported by developers — including a recent Laracasts thread — is that Precognition always returns success, even when the input is invalid. The HandlePrecognitiveRequests middleware seems to do nothing. Here is why and how to fix it.

How Precognition Works

Precognition works by sending a HEAD or POST request with a special X-Precognition header. Laravel detects this header and runs validation without executing the full controller logic. If validation fails, it returns a JSON response with the validation errors. If it passes, it returns a 204 No Content response.

The key middleware is HandlePrecognitiveRequests, which intercepts precognitive requests and returns early with validation results.

The Problem: Precognition Always Returns 200/201

Here is a typical setup that looks correct but silently bypasses Precognition:

<?php

// routes/web.php
use App\Http\Requests\EmailRequest;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
use Illuminate\Support\Facades\Route;

Route::post('/', function (EmailRequest $request) {
    // ... process the request
})->middleware(HandlePrecognitiveRequests::class);

You send a request with the Precognition: true header and invalid data, expecting validation errors. But instead, the request goes through the full controller and returns a 200 or 201 response.

Common Causes and Fixes

1. Missing the X-Precognition Header

This is the most common cause. Precognition requires the Precognition: true header (or X-Precognition depending on your version). Without it, the middleware passes the request through as normal:

// Frontend — WRONG (missing the header)
fetch('/', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({ email: 'invalid' }),
});

// Frontend — CORRECT
fetch('/', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Precognition': 'true', // OR 'X-Precognition': 'true'
    },
    body: JSON.stringify({ email: 'invalid' }),
});

2. Form Request Not Using ValidatesWhenResolved

The HandlePrecognitiveRequests middleware relies on your form request using the ValidatesWhenResolved trait (which it does by default in recent Laravel versions). But if you override the validate method or use manual validation in the controller, Precognition will not work:

<?php

// routes/web.php — WRONG: manual validation bypasses Precognition
Route::post('/', function (Request $request) {
    $validated = $request->validate([
        'email' => 'required|email',
    ]);
    // ... process
})->middleware(HandlePrecognitiveRequests::class);
<?php

// routes/web.php — CORRECT: use a Form Request
Route::post('/', function (EmailRequest $request) {
    // Form request handles validation automatically
    // ... process
})->middleware(HandlePrecognitiveRequests::class);

3. Middleware Order Matters

The HandlePrecognitiveRequests middleware must run before your form request is resolved. If you have other middleware on the route that runs first and calls $request->validate() manually, Precognition will be bypassed:

<?php

// Kernel.php or route — WRONG
Route::post('/', function (EmailRequest $request) {
    // ...
})->middleware(['throttle:api', HandlePrecognitiveRequests::class]);

If throttle or any other middleware calls $request->validate(), the form request validation in the controller will not trigger precognitive behavior. Move HandlePrecognitiveRequests earlier in the pipeline, or remove other middleware that interferes.

4. Inertia.js Configuration

If you are using Inertia.js with Precognition, the frontend setup must use the @inertiajs/inertia-precognition plugin or include the header automatically. Here is the correct Inertia setup:

<script>
import { createInertiaApp } from '@inertiajs/vue3';
import { precognitive } from '@inertiajs/vue3-precognition';

createInertiaApp({
    // ...
    plugins: [
        precognitive(),
    ],
});
</script>
<!-- Vue component -->
<template>
    <form @submit="submit">
        <input
            v-model="form.email"
            @change="form.validate('email')"
        />
        <div v-if="form.invalid('email')">
            {{ form.errors.email }}
        </div>
    </form>
</template>

<script setup>
import { usePrecognition } from '@inertiajs/vue3-precognition';

const form = usePrecognition('post', '/', {
    email: '',
});

function submit() {
    form.submit();
}
</script>

5. Testing Precognition

If you want to test whether Precognition is working, use Laravel's HTTP test helpers with the precognitive header:

<?php

test('precognition validates email field', function () {
    $response = $this->post('/', [
        'email' => 'not-an-email',
    ], [
        'Precognition' => 'true',
    ]);

    $response
        ->assertUnprocessable()
        ->assertJsonValidationErrors(['email']);
});

Quick Debugging Checklist

  1. Open the browser's Network tab and check: is the Precognition: true header being sent?
  2. Are you using a Form Request class (not $request->validate())?
  3. Is HandlePrecognitiveRequests the first middleware on the route? Check with php artisan route:list -v
  4. If using Inertia, have you installed and configured the precognition plugin?
  5. Does the response include X-Precognition: success header when validation passes?

Conclusion

Laravel Precognition silently falls through to normal request handling when it is not configured correctly. The three most common culprits are: not sending the Precognition header, using manual validation instead of a Form Request, or incorrect middleware ordering. Check those first, and Precognition will start returning proper validation errors as expected.

Stefan

Stefan

SEO engineer and Laravel developer. Building tools to help Laravel applications rank higher in search results.

Share this article

Back to Blog