phacility/phabricator · error · PhabricatorEditorURIParserException

Editor pattern "%s" is invalid: the pattern contains an unre

Error message

Editor pattern "%s" is invalid: the pattern contains an unrecognized variable ("%s"). Use "%%%%" to encode a literal percent symbol.

What it means

PhabricatorEditorURIEngine parses the 'editor' URI pattern (from the `editor` config or user preferences) into literal and variable tokens; every %X token must be one of the variables declared in getVariableDefinitions(). The recognized set is %f (file name), %l (line number), %n (repository short name), %d (repository ID), %p (repository PHID), %r (repository callsign) and %% (a literal percent). Any other %-prefixed sequence raises PhabricatorEditorURIParserException at validation time.

Source

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

  private function newRawURITokens() {
    $raw_pattern = $this->getPattern();
    $raw_tokens = self::newPatternTokens($raw_pattern);

    $variable_definitions = self::getVariableDefinitions();

    foreach ($raw_tokens as $token) {
      if ($token['type'] !== 'variable') {
        continue;
      }

      $value = $token['value'];

      if (isset($variable_definitions[$value])) {
        continue;
      }

      throw new PhabricatorEditorURIParserException(
        pht(
          'Editor pattern "%s" is invalid: the pattern contains an '.
          'unrecognized variable ("%s"). Use "%%%%" to encode a literal '.
          'percent symbol.',
          $raw_pattern,
          '%'.$value));
    }

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

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

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

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Replace the offending variable with one of the supported ones: %f, %l, %n, %d, %p, %r, or %% for a literal percent sign.
  2. Find the bad pattern with `./bin/config get editor` and re-set it via `./bin/config set editor '...'` (or remove the per-user override in Settings > Preferences > Editor Link).
  3. Test candidate patterns against PhabricatorEditorURIEngine::newPatternTokens() in a scratch script before deploying the config change.

Example fix

// before: %L and %c do not exist
vim://open?url=file://%f&line=%L&col=%c

// after: only %f and %l are defined
vim://open?url=file://%f&line=%l
Defensive patterns

Strategy: validation

Validate before calling

$pattern = 'vim://open?url=file://%f&line=%l';
$valid = array_keys(PhabricatorEditorURIEngine::getVariableDefinitions());
foreach (PhabricatorEditorURIEngine::newPatternTokens($pattern) as $token) {
  if ($token['type'] === 'variable' && !in_array($token['value'], $valid, true)) {
    throw new Exception('Reject before saving: unknown %'.$token['value']);
  }
}

Try / catch

try {
  $engine = PhabricatorEditorURIEngine::newFromUserPattern($viewer, $pattern);
} catch (PhabricatorEditorURIParserException $ex) {
  $e_pattern = pht('Invalid editor pattern: %s', $ex->getMessage());
  // return the user to the preferences form with the error attached
}

Prevention

When it happens

Trigger: Setting `editor` config or a user preference whose pattern contains an unknown placeholder, e.g. 'vim://open?file=%f&line=%L' (capital %L) or 'emacs://%f:%c' (%c is not defined); the pattern is parsed the moment PhabricatorEditorURIEngine::newFromEnvPattern()/newFromUserPattern() tokenizes it.

Common situations: Copy-pasting an editor URL template from another tool (VS Code, TextMate, IntelliJ) that uses different placeholders; typos in case (%F vs %f); following outdated documentation that lists variables which no longer or never existed; hand-editing a pattern that was never validated on save.

Related errors


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