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 domain.
What it means
The final gate of requireValidRemoteURIForLink(): after protocol checks, PhutilURI->getDomain() must be non-empty. URIs like 'mailto:someone@example.com' variants without a host, 'https:///path', or scheme-only strings pass a protocol test but have no domain, and a link with no host cannot be considered a well-formed remote resource, so the plain Exception is thrown.
Source
Thrown at src/infrastructure/env/PhabricatorEnv.php:749
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)) {
throw new Exception(
pht(
'URI "%s" is not a valid linkable resource. A valid linkable '.
'resource URI must specify a domain.',
$raw_uri));
}
}
/**
* Detect if a URI identifies a valid fetchable remote resource.
*
* @param string URI to test.
* @param list<string> Allowed protocols.
* @return bool True if the URI is a valid fetchable remote resource.
* @task uri
*/
public static function isValidRemoteURIForFetch($uri, array $protocols) {
try {View on GitHub (pinned to 5720a38cfe)
Solutions
- Fix the source value to include a host: 'https://example.com/path'.
- Add a form-level validation that rejects host-less URIs before they reach storage, so users get an inline error instead of an exception at render time.
- For scheme-only URIs (mailto:, tel:) check whether your allowed-protocols entries even make sense - mailto with a domain is nonsensical; consider excluding such schemes from link fields.
Example fix
// before $uri = 'https:///repos/P1'; // no host PhabricatorEnv::requireValidRemoteURIForLink($uri); // throws // after $uri = 'https://phab.example.com/repos/P1'; PhabricatorEnv::requireValidRemoteURIForLink($uri);
Defensive patterns
Strategy: validation
Validate before calling
$uri = new PhutilURI($url);
if (!strlen($uri->getDomain())) {
throw new Exception('URI must include a host: '.$url);
}
PhabricatorEnv::requireValidRemoteURIForLink($url); Type guard
function uriHasDomain($raw) {
return strlen((new PhutilURI($raw))->getDomain()) > 0;
} Try / catch
try {
PhabricatorEnv::requireValidRemoteURIForLink($url);
} catch (Exception $ex) {
// do not link host-less URIs; display them escaped
return htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
} Prevention
- Validate scheme AND host together in custom forms before persistence.
- Prefer PhabricatorURL Remarkup/link fields over storing raw strings - they run these checks for you.
- Beware templating that interpolates an empty host variable into URLs.
When it happens
Trigger: Calling requireValidRemoteURIForLink() with values such as 'https:///just/a/path', 'custom-scheme:' or 'mailto:' with empty remainder - protocol parses, but getDomain() returns '' and strlen() fails.
Common situations: User input that kept only a scheme after cleanup ('https://' alone); templating bugs dropping the host portion; imported records with truncated URLs that lost everything after '://'.
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 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
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/1e35392e2c99ad1d.
Report an issue: GitHub.