phacility/phabricator · error · Exception

Unable to load MySQL blob file '%s'!

Error message

Unable to load MySQL blob file '%s'!

What it means

The MySQL storage engine stores each file's bytes in a blob row keyed by the file's storage handle; loadFromMySQLFileStorage() throws when PhabricatorFileStorageBlob->load($handle) returns nothing. The file metadata row exists and points at a handle, but the blob row for that handle is missing from the database.

Source

Thrown at src/applications/files/engine/PhabricatorMySQLFileStorageEngine.php:90

  public function deleteFile($handle) {
    $this->loadFromMySQLFileStorage($handle)->delete();
  }


/* -(  Internals  )---------------------------------------------------------- */


  /**
   * Load the Lisk object that stores the file data for a handle.
   *
   * @param string  File data handle.
   * @return PhabricatorFileStorageBlob Data DAO.
   * @task internal
   */
  private function loadFromMySQLFileStorage($handle) {
    $blob = id(new PhabricatorFileStorageBlob())->load($handle);
    if (!$blob) {
      throw new Exception(pht("Unable to load MySQL blob file '%s'!", $handle));
    }
    return $blob;
  }

}

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Confirm the row is really gone: SELECT * FROM file_storageblob WHERE id = <handle>
  2. If lost, restore the blob row(s) from a backup taken together with the file table
  3. If unrecoverable, destroy the file record explicitly so the UI shows a deleted file instead of a read error
  4. When migrating storage engines, run the complete storage migration so every file's handle matches the engine that holds its bytes
Defensive patterns

Strategy: try-catch

Validate before calling

$blob = id(new PhabricatorFileStorageBlob())->load($file->getStorageHandle());
if (!$blob) {
  // data row missing: treat file as lost, do not attempt read
}

Try / catch

catch Exception from engine reads, mark the file record as deleted/corrupt in the UI, and log the handle for restoration from backup.

Prevention

When it happens

Trigger: The blob row was deleted manually, a partial database restore recovered the file table but not file_storageblob, or the file's storage handle was recorded against the wrong engine/row.

Common situations: Selective table restores after an incident; manual deletion of 'large' blob rows to reclaim space; incomplete migration between storage engines that left handles pointing at MySQL blobs that were already moved.

Related errors


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