phacility/phabricator · error · PhabricatorEditorURIParserException
Editor pattern "%s" is invalid: the final character in a pat
Error message
Editor pattern "%s" is invalid: the final character in a pattern may not be an unencoded percent symbol ("%%"). Use "%%%%" to encode a literal percent symbol. What it means
newPatternTokens() walks the pattern character by character; a '%' consumes the following character as part of a variable token. A '%' in the final position has no following character, so it is ambiguous (a variable name is missing) and the parser throws PhabricatorEditorURIParserException telling you to use %% to encode a literal percent. This is the trailing-edge case of the same tokenizer used for all editor pattern validation.
Source
Thrown at src/infrastructure/editor/PhabricatorEditorURIEngine.php:322
$result[] = $token_value;
}
$result = implode('', $result);
return $result;
}
public static function newPatternTokens($raw_pattern) {
$token_positions = array();
$len = strlen($raw_pattern);
for ($ii = 0; $ii < $len; $ii++) {
$c = $raw_pattern[$ii];
if ($c === '%') {
if (!isset($raw_pattern[$ii + 1])) {
throw new PhabricatorEditorURIParserException(
pht(
'Editor pattern "%s" is invalid: the final character in a '.
'pattern may not be an unencoded percent symbol ("%%"). '.
'Use "%%%%" to encode a literal percent symbol.',
$raw_pattern));
}
$token_positions[] = $ii;
$ii++;
}
}
// Add a final marker past the end of the string, so we'll collect any
// trailing literal bytes.
$token_positions[] = $len;
$tokens = array();
$cursor = 0;View on GitHub (pinned to 5720a38cfe)
Solutions
- Double the trailing percent: '%%' - e.g. 'vim://open?url=file://%f&rate=100%%'.
- Audit the pattern for any other lone '%' that is not part of %f/%l/%n/%d/%p/%r/%% and escape it as %%; check both `./bin config get editor` and user preferences.
- Validate patterns programmatically with PhabricatorEditorURIEngine::newPatternTokens($pattern) before saving them to config.
Example fix
// before: trailing bare percent vim://open?url=file://%f&pct=90% // after: encoded literal percent vim://open?url=file://%f&pct=90%%
Defensive patterns
Strategy: validation
Validate before calling
if (substr($pattern, -1) === '%') {
throw new Exception(
'Pattern may not end with a bare %; use %% for a literal percent.');
} Try / catch
try {
PhabricatorEditorURIEngine::newPatternTokens($pattern);
} catch (PhabricatorEditorURIParserException $ex) {
// keep the previously saved pattern and report the parse error inline
$errors[] = $ex->getMessage();
} Prevention
- Escape every literal percent as %% when writing editor patterns.
- Run a one-line lint (pattern parses cleanly) in your config management before deploying.
- Remember %-sequences come in pairs: odd trailing counts are a smell.
When it happens
Trigger: Any editor pattern (config `editor` or user preference) whose last character is a single unescaped '%', e.g. 'vim://open?url=%f&rate=100%' - the loop hits $ii+1 beyond the string end and throws before any URI is built.
Common situations: Patterns embedding percent-encoded fragments or literals (a trailing '100%', a URL like '...%25' trimmed wrong); hand-crafted patterns never exercised until a user clicks an editor link; migration scripts concatenating strings that end with '%'.
Related errors
- Editor pattern "%s" is invalid: the pattern contains an unre
- Editor pattern "%s" is invalid: the pattern must begin with
- Unable to parse function and arguments for token "%s".
- Editor pattern "%s" is invalid: the pattern must begin with
- Editor pattern "%s" is invalid: the pattern must begin with
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/8f3b4775d1405d6f.
Report an issue: GitHub.