phacility/phabricator · error · Exception
The underlying file does not exist, but the cached request w
Error message
The underlying file does not exist, but the cached request was successful. This likely means the file record was manually deleted by an administrator.
What it means
Thrown when a cached PhabricatorFileExternalRequest was successful and points at a file PHID, but PhabricatorFileQuery (run as the omnipotent user) cannot load that file record. The proxy cache entry survived while the file row it references is gone, so the cached response can never be served. This is a data-consistency problem, almost always caused by deleting file rows without cleaning dependent records.
Source
Thrown at src/applications/files/controller/PhabricatorFileImageProxyController.php:134
return $this->getExternalResponse($external_request);
}
private function getExternalResponse(
PhabricatorFileExternalRequest $request) {
if (!$request->getIsSuccessful()) {
throw new Exception(
pht(
'Request to "%s" failed: %s',
$request->getURI(),
$request->getResponseMessage()));
}
$file = id(new PhabricatorFileQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs(array($request->getFilePHID()))
->executeOne();
if (!$file) {
throw new Exception(
pht(
'The underlying file does not exist, but the cached request was '.
'successful. This likely means the file record was manually '.
'deleted by an administrator.'));
}
return id(new AphrontAjaxResponse())
->setContent(
array(
'imageURI' => $file->getViewURI(),
));
}
}
View on GitHub (pinned to 5720a38cfe)
Solutions
- Delete the stale file_externalrequest row(s) for that URI so the next request re-fetches the image fresh
- Stop deleting file rows with SQL; destroy objects through Phabricator's destruction tooling (PhabricatorDestructionEngine), which removes dependent records
- Sweep for other dangling references: compare file PHIDs in file_externalrequest against the file table and clean all stale rows in one pass
Example fix
-- before: raw SQL delete leaves a dangling proxy cache row DELETE FROM file WHERE phid = 'PHID-FILE-xxxx'; -- after: destroy through the destruction tooling so dependents are cleaned, -- or remove the now-stale cache row explicitly DELETE FROM file_externalrequest WHERE filePHID = 'PHID-FILE-xxxx';
Defensive patterns
Strategy: fallback
Validate before calling
$file = id(new PhabricatorFileQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs(array($request->getFilePHID()))
->executeOne();
if (!$file) {
// cached entry is unusable: delete the stale request and re-fetch
$request->delete();
} Try / catch
catch the Exception, delete the stale PhabricatorFileExternalRequest row, and re-fetch the image once instead of surfacing the inconsistency.
Prevention
- Never delete file rows with raw SQL; use the destruction engine so dependent records are removed
- Restore files_* tables together when recovering from backups
When it happens
Trigger: An administrator deletes rows from the file table with raw SQL (or restores a partial dump) while file_externalrequest rows still reference the deleted PHID; the image proxy then hits the stale cache entry and fails to load the underlying file.
Common situations: Manual 'cleanup' of large files via SQL; restoring an old file table backup without file_externalrequest; destructive maintenance scripts that bypass PhabricatorDestructionEngine.
Related errors
- Request to "%s" failed: %s
- Specify either "--all" or "--caches", not both.
- Select caches to purge with "--all" or "--caches". Available
- Cache purger "%s" is not recognized. Available caches are: %
- When using "--caches", you must select at least one valid ca
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/3c0c195cddc98d12.
Report an issue: GitHub.