{"record":{"id":"f3bda326fe686bec","repo":"phacility/phabricator","slug":"failed-to-poll-mysqli-connection","errorCode":null,"errorMessage":"Failed to poll mysqli connection!","messagePattern":"Failed to poll mysqli connection!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php","lineNumber":152,"sourceCode":"  protected function rawQuery($raw_query) {\n    $conn = $this->requireConnection();\n    $time_limit = $this->getQueryTimeout();\n\n    // If we have a query time limit, run this query synchronously but use\n    // the async API. This allows us to kill queries which take too long\n    // without requiring any configuration on the server side.\n    if ($time_limit && $this->supportsAsyncQueries()) {\n      $conn->query($raw_query, MYSQLI_ASYNC);\n\n      $read = array($conn);\n      $error = array($conn);\n      $reject = array($conn);\n\n      $result = mysqli::poll($read, $error, $reject, $time_limit);\n\n      if ($result === false) {\n        $this->closeConnection();\n        throw new Exception(\n          pht('Failed to poll mysqli connection!'));\n      } else if ($result === 0) {\n        $this->closeConnection();\n        throw new AphrontQueryTimeoutQueryException(\n          pht(\n            'Query timed out after %s second(s)!',\n            new PhutilNumber($time_limit)));\n      }\n\n      return @$conn->reap_async_query();\n    }\n\n    $trap = new PhutilErrorTrap();\n\n    $result = @$conn->query($raw_query);\n\n    $err = $trap->getErrorsAsString();\n    $trap->destroy();","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php#L134-L170","documentation":"In async mode, the query was dispatched with MYSQLI_ASYNC and the driver then waited with mysqli::poll(); poll() returned false, meaning the poll syscall itself failed (a mysqlnd-level error), which is distinct from a timeout (0) or success. Because the link's state is now unknown, the driver closes the connection before throwing this generic Exception — the query may or may not still be running server-side.","triggerScenarios":"Executing a query with a nonzero per-query time limit (which selects the async path) while the connection breaks: server killed the session (KILL, restart), socket error, network partition, or a mysqlnd bug. Any poll() false maps here.","commonSituations":"Long-running queries under aggressive query timeouts during load spikes; DB failover mid-query; flaky container networking; MySQL restarting under the client.","solutions":["Treat it as a lost connection: the object already closed the link, so re-establish the connection and retry the query once with backoff","Check server-side health at the same moment: MySQL error log, dmesg/network errors, whether someone ran KILL","If it recurs deterministically for one query, run that query without a time limit (synchronous path) to obtain the real underlying error","Ensure the operation is idempotent before retrying, since the original query may have committed"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// The driver already closed the connection; re-establish and retry once:\ntry {\n  $result = queryfx_all($conn_w, '%s', $sql);\n} catch (Exception $ex) {\n  // 'Failed to poll mysqli connection!' => link state unknown.\n  $conn_w = $dao->establishConnection('w');\n  $result = queryfx_all($conn_w, '%s', $sql); // only if idempotent!\n}","preventionTips":["Make async-path queries idempotent (or guarded by a re-check) because the first attempt may have committed server-side","Keep query time limits sane so the async path is not entered casually for every statement","Watch MySQL error logs for KILLs/restarts that coincide with poll failures","If one query deterministically triggers it, reproduce synchronously (no time limit) to get the real error"],"tags":["mysqli","async-query","poll","connection-lost","mysqlnd"],"backgroundTag":"async-query-poll-failure","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}