phacility/phabricator · warning · PhutilSearchQueryCompilerSyntaxException

Query contains unmatched double quotes.

Error message

Query contains unmatched double quotes.

What it means

The search query tokenizer finished scanning the whole input while still inside a double-quoted string ($is_quoted stayed true). Phabricator's query language uses quotes for exact/substring phrases (e.g. `"walk the dog"`, or quoting a term that contains an operator character like `"cat:dog"`), and an opening quote with no closing quote leaves the parser dangling, so it throws PhutilSearchQueryCompilerSyntaxException before compiling.

Source

Thrown at src/applications/search/compiler/PhutilSearchQueryCompiler.php:248

          if ($enable_functions) {
            $token['function'] = $current_function;
          }

          $tokens[] = $token;

          $current_operator = array();
          $current_token = array();
          $current_function = null;
          continue;
        } else {
          $current_token[] = $character;
        }
      }
    }

    if ($is_quoted) {
      throw new PhutilSearchQueryCompilerSyntaxException(
        pht(
          'Query contains unmatched double quotes.'));
    }

    // If the input query has trailing space, like "a b ", we may exit the
    // parser without a final token.
    if ($current_function !== null || $current_operator || $current_token) {
      $token = array(
        'operator' => $current_operator,
        'quoted' => false,
        'value' => $current_token,
      );

      if ($enable_functions) {
        $token['function'] = $current_function;
      }

      $tokens[] = $token;

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Count the double quotes in the query and add the missing closing quote: `fix "typo"`.
  2. If the quote is intentional content (apostrophe/quote inside a word), remove it or quote the whole term so quotes pair up.
  3. For programmatic callers, escape or strip double quotes from user-supplied fragments before embedding them: str_replace('"', '', $fragment) or wrap the whole fragment in one pair of quotes.
  4. Surface this exception to the user as a validation error (it is PhutilSearchQueryCompilerSyntaxException, designed to be user-facing) rather than logging it as a server fault.

Example fix

// before: unbalanced quotes in the query string
$query = 'fix "typo';

// after
$query = 'fix "typo"';
// or programmatically balance/strip
$frag = str_replace('"', '', $user_input);
$query = "fix \"{$frag}\"";
Defensive patterns

Strategy: validation

Validate before calling

// Cheap parity check before submit/compile
if (substr_count($query, '"') % 2 !== 0) {
  $errors[] = pht('Query contains an unmatched double quote.');
}

Type guard

function hasBalancedQuotes($q) { return substr_count($q, '"') % 2 === 0; }

Try / catch

try {
  $tokens = $compiler->tokenizeQuery($query);
} catch (PhutilSearchQueryCompilerSyntaxException $ex) {
  $view->setErrors(array($ex->getMessage())); // render back into the form
}

Prevention

When it happens

Trigger: A query like `fix "typo` (missing closing quote), `"unclosed`, or text where a quote is used as an apostrophe: `don't"t` style input, or a term containing a colon quoted only on one side (`cat:"dog`). Typing in the global search box or any application search field, or sending such a string through Conduit search parameters.

Common situations: Users pasting prose that contains one double quote (e.g. quoted error messages); smart quotes converted to straight quotes on one side only; programmatic callers building queries by concatenating fragments without escaping quotes; a term with a colon partially quoted per the 'surround in double quotes' advice but with one quote forgotten.

Related errors


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