Featured image of post Why Laravel min/max Fails on Numbers: Add the numeric Rule

Why Laravel min/max Fails on Numbers: Add the numeric Rule

Laravel min/max rules compare string length by default, letting 0 pass validation. Add the numeric rule to switch to value comparison and fix the bug.

I used min:1 to reject the number 0, but the validation passed anyway.

Why the min Rule Didn’t Work

You might write the validation like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
namespace App\Http\Controllers;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class MinNumberController extends Controller
{
    public function check(Request $request): JsonResponse
    {
        $request->validate(['value' => 'required|min:1']);

        return response()->json($request->all());
    }
}

A test sending value = 0 should get a 422:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
namespace Tests\Feature\Http\Controllers;

use Tests\TestCase;

class MinNumberControllerTest extends TestCase
{
    public function test_validate_minimum_value(): void
    {
        $response = $this->postJson('/min-number/check', ['value' => 0]);

        $response->assertStatus(422);
    }
}

The test fails — validation passes.

Frontend Data Is Always a String

Data POSTed from the frontend is treated as strings by Laravel. So 0 becomes the string "0", and min:1 checks string length for strings — "0" has length 1, so it passes.

Add numeric so Laravel knows the field is a number, and min will compare values instead:

1
2
3
4
5
6
7
8
9
class MinNumberController extends Controller
{
    public function check(Request $request): JsonResponse
    {
        $request->validate(['value' => 'required|numeric|min:1']);

        return response()->json($request->all());
    }
}

So for number-related validation rules (min, max, between), always add numeric first — otherwise Laravel compares string lengths.