phacility/phabricator · error · Exception
Request to " " failed
Error message
Request to "%s" failed: %s
What it means
Thrown by PhabricatorFileImageProxyController::getExternalResponse() when a cached PhabricatorFileExternalRequest reports an unsuccessful server-side fetch. Phabricator's image proxy downloads remote images on the server (so user browsers never contact the remote host directly) and caches the outcome; this exception re-surfaces the original transport or HTTP error for the proxied URI. The message embeds the requested URI and the cached response message (cURL error or HTTP status text).
Solutions
- From the web host, verify the URI is fetchable: curl -I '<image URL>'; fix or remove the dead hotlink
- Check outbound network/proxy configuration so the Phabricator server can reach the image host (ports 80/443, DNS, TLS trust)
- Delete the cached failed row in file_externalrequest for that URI so the proxy retries instead of replaying the cached error
- If egress is restricted, whitelist the image host or disable the image-proxy feature
Example fix
// before
$response = $this->getExternalResponse($external_request);
return $response;
// after
try {
return $this->getExternalResponse($external_request);
} catch (Exception $ex) {
// URI and transport error are in $ex->getMessage(); degrade gracefully
return id(new AphrontAjaxResponse())
->setContent(array('imageURI' => $default_image_uri));
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!$external_request->getIsSuccessful()) {
// cached outcome is a failure: do not call getExternalResponse()
return $default_image_response;
} Try / catch
try { $response = $this->getExternalResponse($external_request); } catch (Exception $ex) { log $ex->getMessage() (it contains the URI and transport error) and degrade to a default image instead of an uncaught 500. } Prevention
- Validate remote image URLs at embed time and drop dead hotlinks early
- Keep outbound network/proxy egress from the web host healthy and monitored
- Treat cached proxy failures as short-lived: clear file_externalrequest rows for a URI after fixing the remote host
When it happens
Trigger: Loading content that embeds a remote image whose proxied fetch failed: the remote host returned 404/403/500, DNS resolution failed, the connection timed out, or SSL verification failed. Also triggered when a previously cached failure row in file_externalrequest is replayed before its TTL expires.
Common situations: Hotlinked images that were later removed or now require auth; egress firewalls blocking the Phabricator web host; expired TLS certificates on the image host; slow image hosts exceeding the fetch timeout; a stale cache row replaying a transient outage.
Related errors
- The underlying file does not exist, but the cached request…
- Unable to connect to memcache server
- Attempt to connect to
- Cache purger " " is not recognized. Available caches are: .
- Cache returned bogus result!
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/92dfe126281a9389.
Report an issue: GitHub.
Appendix: source
Thrown at src/applications/files/controller/PhabricatorFileImageProxyController.php:122
throw new Exception(
pht(
'Hit duplicate key collision when saving proxied image, but '.
'failed to load duplicate row (for URI "%s").',
$img_uri));
}
}
}
unset($unguarded);
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.'));
}
View on GitHub (pinned to 5720a38cfe)