Skip to content

[13.x] feat: convert QueryException to ModelNotFoundException in implicit route binding#58943

Draft
calebdw wants to merge 1 commit intolaravel:13.xfrom
calebdw:calebdw/push-sxosyvyswkqo
Draft

[13.x] feat: convert QueryException to ModelNotFoundException in implicit route binding#58943
calebdw wants to merge 1 commit intolaravel:13.xfrom
calebdw:calebdw/push-sxosyvyswkqo

Conversation

@calebdw
Copy link
Contributor

@calebdw calebdw commented Feb 20, 2026

Hello!

When implicit route model binding encounters a QueryException (e.g., from integer overflow or type mismatch), convert it to a ModelNotFoundException instead of letting the 500 propagate. This ensures invalid route parameters like /users/99999999999999999999 return a 404 rather than a 500.

This has been the biggest pain, without this you have to add ->whereNumber() on every route OR you litter the AppServiceProvider with 50+ calls like Route::pattern('user', '[0-9]+');. Even with this, we've still had exceptions where the parameter was all digits but it exceeded the column int size so we had to add even more checks to prevent the exception.

Ultimately, a model was not found so end user should always receive a 404 instead of a 500.

The QueryException is still reported, but developers now have the ability to disable reporting, for example:

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        Model::reportRouteModelBindingExceptions(! $this->app->isProduction());
    }
}

Thanks!

@calebdw calebdw changed the title [13.x] feat: convert QueryException to ModelNotFoundException in implicit route binding [13.x] feat: convert QueryException to ModelNotFoundException in implicit route binding Feb 20, 2026
@calebdw calebdw force-pushed the calebdw/push-sxosyvyswkqo branch from ad0a9b6 to e484dc0 Compare February 20, 2026 14:13
@shaedrich
Copy link
Contributor

Is this intentional? 🤔

@calebdw
Copy link
Contributor Author

calebdw commented Feb 20, 2026

Is this intentional? 🤔

Is what intentional? 🧐 I intentionally submitted this PR if that's what you're asking about 🙃

@shaedrich
Copy link
Contributor

No, sorry, should have included the quote, I was looking at 😬 😅

This ensures […] a 404 rather than a 500.

@calebdw
Copy link
Contributor Author

calebdw commented Feb 20, 2026

Lol, I'm not sure. I was trying to keep this PR simple, but if folks want the exception then I can add a way to configure it

@shaedrich
Copy link
Contributor

I guess, that would be great—thanks 👍🏻

@taylorotwell
Copy link
Member

taylorotwell commented Feb 20, 2026

I wonder if this would be hard to debug what is going on, especially if you expect to be getting a model back, you get some query error (maybe a global scope), but now it's masked as a 404. It feels like the current behavior is pretty helpful in local development, but maybe not ideal in prod (though you would still want the original error).

@taylorotwell taylorotwell marked this pull request as draft February 20, 2026 15:27
@calebdw
Copy link
Contributor Author

calebdw commented Feb 20, 2026

Yeah, I could see maybe having some configuration options, maybe something like:

Model::throwRouteModelBindingExceptions();
// and / or maybe just this
Model::reportRouteModelBindingExceptions();

I think from the end user perspective they should always receive a 404 instead of a 500 in production

@shaedrich
Copy link
Contributor

Nice! 👍🏻

@calebdw calebdw force-pushed the calebdw/push-sxosyvyswkqo branch from e484dc0 to 6540965 Compare February 24, 2026 15:23
@calebdw calebdw marked this pull request as ready for review February 24, 2026 15:29
@calebdw
Copy link
Contributor Author

calebdw commented Feb 24, 2026

@taylorotwell, I've updated to report the QueryException, with the option of disabling reporting

…ute binding

When implicit route model binding encounters a QueryException (e.g., from
integer overflow or type mismatch), convert it to a ModelNotFoundException
instead of letting the 500 propagate. This ensures invalid route parameters
like '/users/99999999999999999999' return a 404 rather than a 500.
@calebdw calebdw force-pushed the calebdw/push-sxosyvyswkqo branch from 6540965 to d6e5406 Compare February 24, 2026 15:35
@taylorotwell
Copy link
Member

Hmm, let me think about this one - I'm not confident we're totally landing on the right solution.

@taylorotwell taylorotwell marked this pull request as draft February 25, 2026 19:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants