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.

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.

Appendix: 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)