phacility/phabricator · error · Exception
URI "%s" is not a valid fetchable resource. A valid fetchabl
Error message
URI "%s" is not a valid fetchable resource. A valid fetchable resource URI must specify a protocol.
What it means
PhabricatorEnv::requireValidRemoteURIForFetch() is the stricter sibling of the link validator, used when Phabricator itself will retrieve the URI (repository imports, image fetching, MFA SMS/voice lookups, webhooks). The caller supplies the allowed protocol list; first the URI must carry a non-empty protocol from PhutilURI. A protocol-less target cannot be fetched safely, so it throws before any network activity.
Source
Thrown at src/infrastructure/env/PhabricatorEnv.php:797
*
* A valid fetchable remote resource can be safely fetched using a request
* originating on this server. This is a primarily an address check against
* the outbound address blacklist.
*
* @param string URI to test.
* @param list<string> Allowed protocols.
* @return pair<string, string> Pre-resolved URI and domain.
* @task uri
*/
public static function requireValidRemoteURIForFetch(
$raw_uri,
array $protocols) {
$uri = new PhutilURI($raw_uri);
$proto = $uri->getProtocol();
if (!strlen($proto)) {
throw new Exception(
pht(
'URI "%s" is not a valid fetchable resource. A valid fetchable '.
'resource URI must specify a protocol.',
$raw_uri));
}
$protocols = array_fuse($protocols);
if (!isset($protocols[$proto])) {
throw new Exception(
pht(
'URI "%s" is not a valid fetchable resource. A valid fetchable '.
'resource URI must use one of these protocols: %s.',
$raw_uri,
implode(', ', array_keys($protocols))));
}
$domain = $uri->getDomain();
if (!strlen($domain)) {View on GitHub (pinned to 5720a38cfe)
Solutions
- Normalize the URI before validating: if no scheme, prepend 'https://' (or reject with a user-facing error).
- Pass protocols explicitly per call site (e.g. array('http', 'https') for image fetches) so the whitelist matches what your HTTP client actually supports.
- Test with PhabricatorEnv::isValidRemoteURIForFetch() (non-throwing twin) to branch gracefully instead of catching.
Example fix
// before
PhabricatorEnv::requireValidRemoteURIForFetch($url, array('http', 'https'));
// $url = 'example.com/a.png' -> throws: no protocol
// after
if (!preg_match('/^[a-z][a-z0-9+\.-]*:/i', $url)) {
$url = 'https://'.$url;
}
PhabricatorEnv::requireValidRemoteURIForFetch($url, array('http', 'https')); Defensive patterns
Strategy: validation
Validate before calling
$uri = new PhutilURI($raw);
if (!strlen($uri->getProtocol())) {
if (!preg_match('/^[a-z][a-z0-9+\.-]*:/i', $raw)) {
$raw = 'https://'.$raw; // absolutize bare hosts
}
}
PhabricatorEnv::requireValidRemoteURIForFetch($raw, array('http', 'https')); Type guard
function isFetchableURI($raw, array $protocols) {
$uri = new PhutilURI($raw);
return strlen($uri->getProtocol()) && strlen($uri->getDomain());
} Try / catch
try {
PhabricatorEnv::requireValidRemoteURIForFetch($url, array('http', 'https'));
} catch (Exception $ex) {
// show the user a form error instead of an uncaught 500 during fetch
$e_url = pht('Not a valid fetchable URI: %s', $ex->getMessage());
} Prevention
- Run PhabricatorEnv::isValidRemoteURIForFetch() before initiating any user-driven fetch.
- Always pass an explicit protocol list matched to your HTTP client's capabilities.
- Absolutize scheme-less input at the boundary; never let raw user strings reach the fetcher.
When it happens
Trigger: Calling requireValidRemoteURIForFetch($uri, array('http','https')) with $uri like 'example.com/file.png' or '/local/path' - PhutilURI->getProtocol() returns '' and the exception fires before DNS or HTTP layers run.
Common situations: User-supplied image/avatar/import URLs pasted without a scheme; stored rows from an older schema that hold relative URLs; glue code forwarding a 'url' request parameter directly into a fetch call.
Related errors
- URI "%s" is not a valid fetchable resource. A valid fetchabl
- URI "%s" is not a valid fetchable resource. A valid fetchabl
- URI "%s" is not a valid fetchable resource. The domain "%s"
- URI "%s" is not a valid linkable resource. A valid linkable
- URI "%s" is not a valid linkable resource. A valid linkable
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/5acf74d802b30cfb.
Report an issue: GitHub.