sentry-laravel: ErrorException: Warning: PDO::prepare(): MySQL server has gone away
There 's a few tickets in the Laravel repositories, but it looks like the reason is an upgrade of the Sentry library to 1.0
Basically we all see ErrorException Warning: PDO::prepare(): MySQL server has gone away reports in Sentry, while it supposed to be caught by Laravel, and handle it.
But since the 1.0 update of Sentry library, it somehow bubbles up đ
https://github.com/laravel/horizon/issues/583 https://github.com/laravel/framework/issues/28920
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 10
- Comments: 33 (3 by maintainers)
Thanks for the info, maybe something with the log channel integration causing issues still. I know we fixed it when not using log channels. Weâre looking!
@shengslogar I donât think there is anything Laravel or Sentry can or should do.
I have discussed this with a few people and we think this is more a âbugâ in PDO.
Iâll tell you why we think that.
When this error occurs âMySQL server has gone awayâ and others like it PDO throws an exception and generates an error with the
E_WARNINGlevel. There is no way in PHP to prevent a warning short of prefixing a function call with@which is generally accepted to be a bad ideaâ˘. In my opinion if PDO throws the Exception the warning should not be generated. Laravel captures the Exception thrown and handles it gracefully but Sentry captures the error.I want to emphasize that although Sentry says
ErrorExceptionit actually is an error (there is a difference). That is because in the SDK we convert the PHP error to an exception so we can log it to Sentry (hence theErrorException, see: https://github.com/getsentry/sentry-php/blob/master/src/ErrorHandler.php#L346).As for the âfixâ of not sending it to Sentry, you can also use a class like this:
And you can use this in your
sentry.phpconfig file like:@Mult1Hunter I had the same issue; my guess is the
App\Exceptions\Handleris not run on the queue. Hereâs some experimental code I put in myconfig/sentry.phpfile successfully (see docs onbefore_send):Obligatory disclaimer to any future copy-pasters that this will suppress even legitimate database issues, so keep whatever other notifications you have available to you on, or just deal with getting false positives.
CC @stayallive since youâre the only Sentry member so far. Is this being actively looked into?
Without going too far down the rabbit hole, I have an idea of where/why this is happening, but not necessarily the best way to solve this.
Whenever a query fails because of a lost connection (determined by the DetectsLostConnections trait), Laravel catches the exception and retries it â as others have stated. However, it always logs the query in the form of a
QueryExecutedevent. See here and here.Sentry appropriately picks up on this (see here, ref-ing 1.1.0 since this is the version Iâm on) as it always has, but I think the reason this is only being reported now is the addition of this block in recent versions (specifically the
flushEventsmethod):https://github.com/getsentry/sentry-laravel/blob/1e5f644b62ee73424ad8316e37b9a2dcf7290de8/src/Sentry/Laravel/EventHandler.php#L113-L119
This change was part of a1b66de5a629fcfd089d789de75244910912b6d7, explicitly added to improve queue reporting.
So technically Sentry is now reporting errors it always shouldâve, but because of the way Laravel is logging failed queries, I donât see any good way to distinguish between an actually failed query and a failed-but-successfully-retried query without making a change to Laravelâs logging (e.g. moving the
logQuerymethod into thetry{}block or something similar).String matching through Sentry is a good âfixâ for now, but this will obviously cause actual failed queries to be ignored.
I donât know enough about the internals of either codebases to recommend a good, accepted solution, but hopefully this will give a jumpstart to any efforts to resolve this.
sentry/sentry-laravel1.6.2was just released which fixes the regression causing duplicate exceptions, thanks all for the information and patience!Ahhh gotcha, this makes sense. Then I think the culprit is found. Will be fixed soon-ish (in the next few days).
I had the same issue with latest version
I use log channels alone
composer.lock
config/logging.php
This issue was closed however I never mentioned we think itâs fixed in
1.4.0, please do open it back up or open a new issue if the problem is not solved.@stayallive Okay, I think I understand now.
So regarding the
error_typesoption:captureExceptionmethod doesnât apply theerror_typesfilter â only the Sentry native error handler doescaptureException(which would not include the PDO warning it catches)âŚwould I then be correct to assume most of the errors Sentry is natively receiving are redundant? And as a result (and related to your original point), I would be safe with even the most aggressive
error_typesfilter as long as I was only concerned about Laravel-reported issues?My last firing brain cell appreciates all your help.
It is possible that the PHP bug is this one: https://bugs.php.net/bug.php?id=63812
@Mult1Hunter The premise is that the same errors get thrown when there is a lost connection AND an actual database issue. Laravel is wired to retry a request once if it thinks it could be a lost connection, and then fail if it doesnât work that time. Since weâre writing a blanket statement to suppress specific errors, we have no way of determining if itâs because there was a lost connection (and successfully reconnected) or if thereâs actually a legitimate issue with your database. This is the same issue Sentry has internally which is creating this whole problem to begin with.
This is why if you donât have separate database monitoring alerts available to you and youâre concerned about your database actually failing, I would recommend against implementing this solution and just deal with the false alerts.
@stayallive Thanks for your reply! So it sounds like at this point we should close out this issue and move towards making a PR to Laravel itself to not log âfalseâ errors in this context.
@LasseRafn Nice! Right on. Totally forgot about the serializing closures thing.
While the above
before_sendsolution might work, it will prevent config caching.I suggest creating a service provider, and putting it in the boot method as follows:
As far as we can tell short of error supressing database calls (putting the
@character in front of these calls: https://d.bouma.dev/3XfflIwWpJn0) the warning cannot be prevented even if the Exception that is also generated is caught by a framework like Laravel (which handles this warning gracefully and retries).As far as the context below people seem to agree (although older answer) the only way to prevent this warning is to not capture warnings (which Sentry does do).
I am not sure this is anything we can do apart from hardcode the warning supressing it from the SDK but that seems like a horrible band-aid fix that possibly will supress those warnings where it does matter.
Open to ideas!
@shengslogar Uff, nice implementation! Can you elaborate why this would silence legitimate database issues? To me it looks like this would only silence exceptions that contain
'Error while sending STMT_PREPARE packet', 'server has gone away'. Thanks for sharing, will give this a try!@shengslogar, we convert it to an ErrorException (https://github.com/getsentry/sentry-php/blob/master/src/ErrorHandler.php#L346) because Sentry has no notion of a âerrorâ and it has no real representation, so we use the (Silenced)ErrorException to encapsulate PHP errors. So changing the error_types will 100% work in this specific case đ
But yes, this will silence all errors of the type âwarningâ.