phacility/phabricator · error · Exception

There are some results left in the result set.

Error message

There are some results left in the result set.

What it means

The mysqli driver's counterpart of the unconsumed-results check: after every expected statement was fetched via next_result()/store_result(), $conn->more_results() still reports pending result sets. The server produced more result sets than the client consumed, so the driver aborts instead of silently discarding them. Typically caused by multiple statements in one call or a stored procedure returning extra sets.

Source

Thrown at src/infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php:222

      if (!$have_result) {
        // End line in front of semicolon to allow single line comments at the
        // end of queries.
        $have_result = $conn->multi_query(implode("\n;\n\n", $raw_queries));
      } else {
        $have_result = $conn->next_result();
      }

      array_shift($raw_queries);

      $result = $conn->store_result();
      if (!$result && !$this->getErrorCode($conn)) {
        $result = true;
      }
      $results[$key] = $this->processResult($result);
    }

    if ($conn->more_results()) {
      throw new Exception(
        pht('There are some results left in the result set.'));
    }

    return $results;
  }

  protected function freeResult($result) {
    $result->free_result();
  }

  protected function fetchAssoc($result) {
    return $result->fetch_assoc();
  }

  protected function getErrorCode($connection) {
    return $connection->errno;
  }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Split multi-statement strings into one queryfx() call per statement
  2. Consume all result sets when a procedure legitimately returns several, or avoid procedures through this API
  3. Log and inspect the exact SQL sent to catch accidental embedded statements
  4. Keep the expected query count and the actual statement count in sync in custom query loops

Example fix

// before: two statements, one call
queryfx($conn_m, 'DELETE FROM a; DELETE FROM b;');

// after: one statement per call
queryfx($conn_m, 'DELETE FROM a');
queryfx($conn_m, 'DELETE FROM b');
Defensive patterns

Strategy: validation

Validate before calling

// Guard the input: exactly one statement per call on the mysqli path too.
if (preg_match('/;\s*\S/', trim($raw_query))) {
  throw new Exception('Split multi-statement SQL into separate calls.');
}

Prevention

When it happens

Trigger: Passing several ';'-separated statements through one queryfx()/queryf() call on the mysqli path; invoking a stored procedure that emits multiple result sets; stray trailing semicolons or concatenation adding statements to the query string.

Common situations: Executing migration scripts written as single multi-statement blobs; wrapping logic in stored procedures; copy-pasting SQL from a dump into a single query call.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/433e109724add85f. Report an issue: GitHub.