phacility/phabricator · warning · PhutilSearchQueryCompilerSyntaxException

Query contains a token

Error message

Query contains a token ("%s") with no search term. Query tokens specify text to search for.

What it means

After operator resolution a token ended up with an empty value while its operator requires text (require_value). Search tokens must specify something to search for; operators like a bare `+` or `-`, or a function prefix with no term (`title:`), produce a token whose value has zero length, which cannot compile into any meaningful query, so PhutilSearchQueryCompilerSyntaxException is thrown with the display form of the offending token.

Solutions

  1. Remove the dangling operator or add the missing term: `cat -` -> `cat`, `title:` -> `title:ship`.
  2. When generating queries in code, skip emission whenever the term is empty: if ($term === '') continue; before prefixing operators.
  3. Trim the query before submit so accidental trailing operators from deleted words are caught by eye.
  4. Treat the exception as form validation: catch PhutilSearchQueryCompilerSyntaxException and re-show the query form with the message; the token is named in the error.

Example fix

// before: emits operator with empty term when filter empty
$parts[] = ($negate ? '-' : '').$term;

// after: skip empty terms entirely
if ($term !== '') {
  $parts[] = ($negate ? '-' : '').$term;
}
Defensive patterns

Strategy: validation

Validate before calling

// Drop operator-only fragments before submitting
$fragments = preg_split('/\s+/', trim($query));
$fragments = array_filter($fragments, function ($f) { return trim($f, '+-:') !== ''; });
$query = implode(' ', $fragments);

Type guard

function hasNoEmptyTokens($q) { return !preg_match('/(^|\s)[+-]+(:\w+)?(\s|$)/', $q); }

Try / catch

try {
  $compiled = $compiler->compileQuery($field, $query);
} catch (PhutilSearchQueryCompilerSyntaxException $ex) {
  $e_query = $ex->getMessage(); // AphrontFormView error binding pattern
}

Prevention

When it happens

Trigger: Queries like `cat +` or `cat -` (trailing operator with no term), `title:` with nothing after the colon, an empty quoted phrase `""` where functions require a value, or a lone function name with functions enabled but no argument. Hit via UI search boxes, saved-query editing, or Conduit search parameters.

Common situations: Trailing space plus operator at the end of a query left over from deleting a word (`fix -` after removing the excluded term); copy-pasted queries where the term after an operator got dropped; programmatic query builders appending an operator prefix then an empty string term.

Related errors


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

Appendix: source

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

            } else {
              $require_value = true;
            }
            break;
          case self::OPERATOR_SUBSTRING:
            if ($enable_functions && ($token['function'] !== null)) {
              $operator = self::OPERATOR_PRESENT;
              $value = null;
            } else {
              $require_value = true;
            }
            break;
          default:
            $require_value = true;
            break;
        }

        if ($require_value) {
          throw new PhutilSearchQueryCompilerSyntaxException(
            pht(
              'Query contains a token ("%s") with no search term. Query '.
              'tokens specify text to search for.',
              $this->getDisplayToken($token)));
        }
      }

      $result = array(
        'operator' => $operator,
        'quoted' => $is_quoted,
        'value' => $value,
        'raw' => $this->getDisplayToken($token),
      );

      if ($enable_functions) {
        // If a user provides a query like "title:a b c", we interpret all
        // of the terms to be title terms: the "title:" function sticks
        // until we encounter another function.

View on GitHub (pinned to 5720a38cfe)