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 use one of these protocols: %s.

What it means

The second gate of requireValidRemoteURIForLink(): the URI's protocol must be a key of the `uri.allowed-protocols` config (by default http, https, mailto, and a few others). This whitelist blocks schemes like javascript:, data:, or file: from ever becoming a link Phabricator renders or redirects to. The exception message lists the currently allowed protocols for quick diagnosis.

Source

Thrown at src/infrastructure/env/PhabricatorEnv.php:739

   * @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)) {
      throw new Exception(
        pht(
          'URI "%s" is not a valid linkable resource. A valid linkable '.
          'resource URI must specify a domain.',
          $raw_uri));
    }
  }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Either change the URI to an allowed scheme (usually https) or extend the whitelist: `./bin/config set uri.allowed-protocols '{"http":true,"https":true,"mailto":true,"ftp":true}'` (set replaces the whole map - merge existing keys).
  2. Audit the failing value: the exception message itself prints the allowed list; compare against the scheme you passed.
  3. Keep the whitelist minimal - each added scheme is a potential phishing/SSRF surface in rendered links.

Example fix

# before
PhabricatorEnv::requireValidRemoteURIForLink('ftp://example.com/pkg.tar.gz');
// throws: ftp not allowed

# after: allow ftp explicitly
$ ./bin/config set uri.allowed-protocols '{"http":true,"https":true,"mailto":true,"ftp":true}'
Defensive patterns

Strategy: validation

Validate before calling

$proto = (new PhutilURI($url))->getProtocol();
$allowed = PhabricatorEnv::getEnvConfig('uri.allowed-protocols');
if (!isset($allowed[$proto])) {
  // either rewrite to https or reject before rendering a link
  $url = PhabricatorURI::convertToHTTPS($url);
}

Try / catch

try {
  PhabricatorEnv::requireValidRemoteURIForLink($url);
} catch (Exception $ex) {
  return id(new PHUITagView())->setName($url)->setType(PHUITagView::TYPE_INVALID);
}

Prevention

When it happens

Trigger: requireValidRemoteURIForLink() receiving a URI whose scheme is outside the whitelist - e.g. 'ftp://example.com/file' when 'ftp' is not configured, or a custom app scheme added by an extension without updating `uri.allowed-protocols`.

Common situations: Linking to ftp://, git://, irc://, or ssh:// resources from remarkup or link fields on installs that never widened the whitelist; disabling protocols centrally for security and having old content fail to render; extensions introducing new schemes.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/503da09f26bfc5b0. Report an issue: GitHub.