Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

laracoft's avatar

Unable to catch PDOException

Hi, I have the following code that catches only PDO exceptions and let the framework handle other exceptions. It works prior to using it in Laravel. Now, Laravel catches it and stops the code from running any further, I also provided the the exception trace after the code fragment.

How can I catch and handle only the PDO exceptions myself and let Laravel do the rest? Thank you.

try {
    $this->runQueryRetry($sql, $binding);
}
catch (\PDOException $e) {
    // catch and handle exception            
}

private function runQueryRetry($sql, $bindings, $options = array())
{
    $statement = $this->pdo->prepare($sql);
    $this->bindParams($statement, $bindings);
    $statement->execute();  // this line throws an exception as mysql has close the connection and gone away
}
  ErrorException  : Error while sending QUERY packet. PID=28295

  at /RPDO.php:158
    ...

  Exception trace:

  1   PDOStatement::execute()
      /RPDO.php:158

  2   RPDO::runQueryRetry("INSERT INTO `table` ( id, `from`,`name` ) VALUES
                        ( NULL, ?,? ) ", [])
      /RPDO.php:650

  Please use the argument -v to see more details.
0 likes
32 replies
jlrdw's avatar

Why would you insert null for Id.

jlrdw's avatar

For auto increment you just leave out that value. MySQL takes care of it.

laracoft's avatar

@jlrdw sorry, but i think we are digressing, I'm specifically trying to deal with the "mysql has gone away" issue as this code is a long running daemon. I need to catch the "gone away" exception and do a reconnect. But somehow Laravel catches the exception before my code. How do I catch the exception before Laravel?

jlrdw's avatar

Back to subject I use the pdo instance quite often, getPdo (), in laravel you don't have to try catch this, laravel also takes care of that.

Do you need an example of getPdo usage.

laracoft's avatar

@jlrdw do you have an example of how I can do a try catch? This code is from another library and I think moving it to getPdo() might involve much more work.

jlrdw's avatar

The only example I would have on that would actually be straight from the PHP manual.

But getPdo is actually the raw PDO instance, same as using straight PDO.

laracoft's avatar

I see, but the PDO gets initialized by this library prior and it's a lot of stuff to go through. It is just puzzling how I'm not able to catch exception in a try catch block

Jaytee's avatar

What is the library that you're using? Do you have a link to the repository?

jlrdw's avatar

Are you sure the library isn't taking care of it.

laracoft's avatar

I found a quick way to reproduce the gone away exception. Oddly, only catch (\Exception $e) works, catch (\PDOException $e) does not catch anything. My question would be answered if someone can explain why this is happening. Thank you.

laracoft's avatar

@jaytee it is a (quite heavily) modified version of RedBeanPHP https://github.com/gabordemooij/redbean @jlrdw I'm sure it is not taking care of it, because I added it myself while on an earlier framework

Suffice to say, I understand there are better practices to get this resolved, but I don't have much time to spend on migration, just need to get this gone away issue handled.

Thank you.

jlrdw's avatar

Where you have the try catch isn't the pdo, the pdo is:

$statement = $this->pdo->prepare($sql);
    $this->bindParams($statement, $bindings);
    $statement->execute();  // this line throw

So catch (\Exception $e) would be correct, sorry I did not catch it earlier.

laracoft's avatar

@jlrdw do you mean $statement->execute() will never throw a PDOException? Why is that? I was using PDOException all along.

jlrdw's avatar

No no, this

   $statement = $this->pdo->prepare($sql);
    $this->bindParams($statement, $bindings);
    $statement->execute();  // th

is the pdo, and where a pdo exception would go.

The top part is not the pdo. so only exception there worked.

this is your top part:

    $this->runQueryRetry($sql, $binding);  // not pdo, just calling pdo


laracoft's avatar

@jlrdw My understanding is that exceptions are nested, meaning if try-catch block is in parent() and parent() calls a child() that throws an exception, it will be caught in parent(), you seem to be saying otherwise.

laracoft's avatar

@jaytee I confirm there is this line in my code $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);, thus I'm expecting exceptions.

jlrdw's avatar

Just put the try catch around the PDO.

But I don't think it's needed I've never put a try catch around pdo except for the connection.

Edit: in fact and your case I think exception is all you need, I use laravel so much now been a while since I've dealt with try catch.

laracoft's avatar

@jlrdw I tested your suggestion just to make sure I left no stone unturned. Unfortunately, it confirms my earlier explanation, exceptions are nested. They will surface to the earlier try-catch block even if it is not within the same function.

Let's stick to explaining why PDOExceptions are not thrown/caught by my code like they used to in the previous framework.

jlrdw's avatar
$this->runQueryRetry($sql, $binding);

private function runQueryRetry($sql, $bindings, $options = array())
{
 try {
$statement = $this->pdo->prepare($sql);
    $this->bindParams($statement, $bindings);
    $statement->execute();  

    }
catch (\PDOException $e) {
    // catch and handle exception            
    }
}

Jaytee's avatar

Probably going to need to update the app/Exceptions/Handler.php class to exclude Laravel from handling PDOExceptions.

// I'm just writing this out without looking at the full method signature, but I think you get the point
public function report(Exception $exception)
{
    if (!$exception instanceof PDOException) {
        parent::report($exception);
    }
}

There would be a problem with this, if you're also using Eloquent. But if you're just using the previous frameworks code, you should be fine.

laracoft's avatar

@jaytee I tried, but $exception is an instance of ErrorException, not PDOException

Jaytee's avatar

Was your previous framework running on PHP 5?

laracoft's avatar

@jaytee good question. It definitely was, but I don't recall whether it ran on PHP 7, it might or might not have. To be clear, I only want to handle PDOException and let Laravel handle all other exceptions, and when I eventually find the time, I will migrate it to use whatever Laravel provides.

Actually, I have working solution by switching to catch ErrorException and it works. I can grudgingly accept it for now because the code has performed very well without throwing other exceptions previously.

Jaytee's avatar

I've done some reading:

The ErrorException will be due to the error you received in your thread code. Based on research, this usually happens due to trying to send too much data.

So i'm guessing, the connection is alive to PDO, therefore it's not throwing an error. When the connection dies, then it'll throw the PDOException.

PHP 5 and PHP7 versions will play a big difference with this.

laracoft's avatar

@jaytee I'm quite sure my error is something else.

  1. Start my PHP code, it runs in the command line as a daemon
  2. Restart mysqld, my daemon continues running without problem
  3. Trigger my daemon to read the database, ErrorException is thrown with "mysql has gone away"
  4. The connection cannot possibly be alive as I have restarted mysqld in step 2
  5. The message in #3 further reinforces that the connection is no longer alive

My question is, why isn't a PDOException thrown like previously?

Jaytee's avatar

I've done some more digging. This whole thing is interesting.

I think i've found the solution:

This isn't Laravel related, although, how Laravel currently handles this error is indeed a flaw. But that is only relevant when using the ->getPdo() methods provided with Laravel. From what i've read, Laravel would convert this to a QueryException in some cases, but it's also unpredictable.

Since this is pure PDO, it seems to be a PHP 7 issue, that's still open and has no solution. There are also cases where warnings are being displayed with the exceptions too.

The two solutions are to catch either Exception or ErrorException. I think this is a bug that's been introduced with the changes to exceptions in PHP 7.

PHP 5 would work fine. But of course, I wouldn't recommend going back to PHP 5.

Next

Please or to participate in this conversation.