phacility/phabricator · error · PhabricatorEditorURIParserException

Editor pattern "%s" is invalid: the pattern must begin with

Error message

Editor pattern "%s" is invalid: the pattern must begin with a valid editor protocol, but begins with a variable. This is very sneaky and also very forbidden.

What it means

After tokenizing the editor pattern, the engine requires the very first token to be a literal string so it can extract a leading protocol (e.g. 'macvim://'). If the pattern starts with a variable token (first token type is not 'literal'), no protocol can be determined safely - substituting user data before the protocol would let the resulting URI claim any scheme - so parsing fails fast with PhabricatorEditorURIParserException.

Source

Thrown at src/infrastructure/editor/PhabricatorEditorURIEngine.php:201

    }

    $variables = array(
      '%' => '%',
    );

    $tokens = $this->newTokensWithVariables($raw_tokens, $variables);

    $first_literal = null;
    if ($tokens) {
      foreach ($tokens as $token) {
        if ($token['type'] === 'literal') {
          $first_literal = $token['value'];
        }
        break;
      }

      if ($first_literal === null) {
        throw new PhabricatorEditorURIParserException(
          pht(
            'Editor pattern "%s" is invalid: the pattern must begin with '.
            'a valid editor protocol, but begins with a variable. This is '.
            'very sneaky and also very forbidden.',
            $raw_pattern));
      }
    }

    $uri = new PhutilURI($first_literal);
    $editor_protocol = $uri->getProtocol();

    if (!$editor_protocol) {
      throw new PhabricatorEditorURIParserException(
        pht(
          'Editor pattern "%s" is invalid: the pattern must begin with '.
          'a valid editor protocol, but does not begin with a recognized '.
          'protocol string.',
          $raw_pattern));

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Rewrite the pattern so it begins with a literal protocol prefix, e.g. 'macvim://open?url=file://%f&line=%l'.
  2. Check the effective value with `./bin/config get editor` and per-user preference overrides; fix whichever layer holds the malformed pattern.
  3. Keep variables only in the query/path portion of the pattern (%f, %l, %n, %d, %p, %r, %%).

Example fix

// before: starts with a variable - no parseable protocol
%n://open?file=%f&line=%l

// after: literal protocol first, variables after
macvim://open?url=file://%n/%f&line=%l
Defensive patterns

Strategy: validation

Validate before calling

$first = PhabricatorEditorURIEngine::newPatternTokens($pattern);
if (!$first || $first[0]['type'] !== 'literal') {
  // pattern starts with a variable: no protocol can be extracted
  return new AphrontRequestValidationErrorException(
    AphrontRequestValidationErrorType::ERROR_INVALID,
    'pattern',
    pht('Pattern must begin with a literal protocol like \'macvim://\'.'));
}

Try / catch

try {
  PhabricatorEditorURIEngine::newPatternTokens($pattern);
} catch (PhabricatorEditorURIParserException $ex) {
  // show the exception text verbatim - it names the exact defect
  $errors[] = $ex->getMessage();
}

Prevention

When it happens

Trigger: An editor pattern whose first character sequence is a substitution, e.g. '%f' or '%n://open?file=%f' - the foreach in newRawURITokens() finds no literal token in position 0 and first_literal stays null, throwing immediately.

Common situations: Users templating the scheme itself ('%r://open?...') expecting per-repository editors; concatenating patterns programmatically and accidentally trimming the literal prefix; copying a pattern where the leading scheme literal was dropped in translation.

Understand the failure class

Related errors


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