phacility/phabricator · error · Exception
URI "%s" is not a valid linkable resource. A valid linkable
Error message
URI "%s" is not a valid linkable resource. A valid linkable resource URI must specify a protocol.
What it means
PhabricatorEnv::requireValidRemoteURIForLink() validates a URI that Phabricator will render as a clickable link or redirect to. The first gate is a protocol check: PhutilURI->getProtocol() must return a non-empty string. A relative URI ('/path'), protocol-relative ('//host/path'), or garbage string yields no protocol and the plain Exception is thrown. This is an anti-open-redirect / anti-javascript-URI measure.
Source
Thrown at src/infrastructure/env/PhabricatorEnv.php:730
/**
* Detect if a URI identifies a valid linkable remote resource, throwing a
* detailed message if it does not.
*
* A valid linkable remote resource can be safely linked or redirected to.
* This is primarily a protocol whitelist check.
*
* @param string URI to test.
* @return void
* @task uri
*/
public static function requireValidRemoteURIForLink($raw_uri) {
$uri = new PhutilURI($raw_uri);
$proto = $uri->getProtocol();
if (!strlen($proto)) {
throw new Exception(
pht(
'URI "%s" is not a valid linkable resource. A valid linkable '.
'resource URI must specify a protocol.',
$raw_uri));
}
$protocols = self::getEnvConfig('uri.allowed-protocols');
if (!isset($protocols[$proto])) {
throw new Exception(
pht(
'URI "%s" is not a valid linkable resource. A valid linkable '.
'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
- Give the URI an explicit allowed scheme: 'https://example.com/page' instead of 'example.com/page' or '//example.com/page'.
- If the target is local, skip this validator - it is meant for remote resources; link locally with a relative path at render time instead.
- Sanitize user-supplied redirect targets before validation: prepend 'https://' when no scheme is present, or reject early with a form error.
Example fix
// before
PhabricatorEnv::requireValidRemoteURIForLink($next); // $next = '/x' -> throws
// after
$next = PhabricatorURI::normalize($next);
if (!PhabricatorEnv::isValidURIForLink($next)) {
$next = '/'; // keep navigation local instead of failing
}
// or store the remote target fully qualified:
$uri = 'https://'.$host.$path; Defensive patterns
Strategy: validation
Validate before calling
$uri = new PhutilURI($candidate);
if (!strlen($uri->getProtocol())) {
// no scheme: absolutize or reject before calling the validator
$candidate = 'https://'.ltrim($candidate, '/');
$uri = new PhutilURI($candidate);
}
PhabricatorEnv::requireValidRemoteURIForLink($candidate); Type guard
function uriHasProtocol($raw) {
return strlen((new PhutilURI($raw))->getProtocol()) > 0;
} Try / catch
try {
PhabricatorEnv::requireValidRemoteURIForLink($url);
} catch (Exception $ex) {
// treat as non-linkable: render as plain text, never as <a href>
return phutil_escape_html($url);
} Prevention
- Always store absolute URIs with scheme in link-typed fields; reject bare hosts at the form layer.
- Use PhabricatorEnv::isValidURIForLink() for a boolean check when you want graceful degradation.
- Feed redirect targets through this validator before issuing redirects - it is your open-redirect guard.
When it happens
Trigger: Passing a relative or malformed URI to requireValidRemoteURIForLink() - e.g. an external-link field or redirect target saved as '/jump/to/x' or 'example.com/page' with no scheme; the check runs at read/render time or on save depending on the calling field.
Common situations: Users pasting bare domains into link/remarkup external-link fields; imports that stored relative URLs; code feeding request-supplied 'next' parameters into the validator without normalization.
Related errors
- URI "%s" is not a valid linkable resource. A valid linkable
- URI "%s" is not a valid fetchable resource. A valid fetchabl
- URI "%s" is not a valid linkable resource. A valid linkable
- URI "%s" is not a valid fetchable resource. A valid fetchabl
- URI "%s" is not a valid fetchable resource. A valid fetchabl
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/78cc0e64ecaf06c3.
Report an issue: GitHub.