{"record":{"id":"45e0e7468848fbe0","repo":"phacility/phabricator","slug":"query-has-an-invalid-sequence-of-operators-s","errorCode":null,"errorMessage":"Query has an invalid sequence of operators (\"%s\").","messagePattern":"Query has an invalid sequence of operators \\(\"(.+?)\"\\)\\.","errorType":"validation","errorClass":"PhutilSearchQueryCompilerSyntaxException","httpStatus":null,"severity":"warning","filePath":"src/applications/search/compiler/PhutilSearchQueryCompiler.php","lineNumber":314,"sourceCode":"            // search mode is normally useless.\n            if (phutil_utf8_is_cjk($value)) {\n              $use_substring = true;\n            } else if (phutil_preg_match('/^_/', $value)) {\n              // See T13632. Assume users searching for any term that begins\n              // with an undescore intend to perform substring search if they\n              // don't provide an explicit search function.\n              $use_substring = true;\n            }\n          }\n\n          if ($use_substring) {\n            $operator = self::OPERATOR_SUBSTRING;\n          } else {\n            $operator = self::OPERATOR_AND;\n          }\n          break;\n        default:\n          throw new PhutilSearchQueryCompilerSyntaxException(\n            pht(\n              'Query has an invalid sequence of operators (\"%s\").',\n              $operator_string));\n      }\n\n      if (!strlen($value)) {\n        $require_value = $is_quoted;\n\n        switch ($operator) {\n          case self::OPERATOR_NOT:\n            if ($enable_functions && ($token['function'] !== null)) {\n              $operator = self::OPERATOR_ABSENT;\n              $value = null;\n            } else {\n              $require_value = true;\n            }\n            break;\n          case self::OPERATOR_SUBSTRING:","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/search/compiler/PhutilSearchQueryCompiler.php#L296-L332","documentation":"While resolving a token's operator string (the sequence of +, -, and function prefixes like `title:` or `sub:`), the compiler hit a combination that has no defined meaning and fell into the default branch of the operator-resolution switch. Only well-formed combinations such as a single AND, NOT, SUBSTRING, or their negated/quoted variants are legal; anything else (e.g. `+-word`, `--word`, `+-sub:word`) is rejected with PhutilSearchQueryCompilerSyntaxException.","triggerScenarios":"Queries like `+-cat`, `-+cat`, `--cat`, `+-title:cat`, or stacking function prefixes `title:body:cat`; also operators glued together with no term between them (`a - + b` can collapse into a bogus operator sequence). Produced from the search box, saved queries, or Conduit search 'query' parameters.","commonSituations":"Users hand-editing saved queries and fat-fingering operator combos; scripts constructing queries by concatenating optional `-` prefixes (e.g. `($exclude ? '-' : '').($include ? '+' : '').$term` producing `+-term`); users trying to boost AND negate at once, which the language does not support.","solutions":["Use exactly one leading operator per token: `-cat` (exclude) or `+cat`/`cat` (require) - never both.","If building queries in code, collapse any operator stack to a single character before emitting: keep the last operator, drop the rest.","For field functions use one function prefix per token (`title:cat`, `-title:cat`); combine field restrictions as separate tokens, not stacked prefixes.","Re-enter the query manually in the UI; the offending operator string is printed in the exception message (`invalid sequence of operators (\"+-\")`)."],"exampleFix":"// before: concatenating flags can stack operators\n$prefix = ($exclude ? '-' : '').($require ? '+' : '');\n$query = $prefix.$term;\n\n// after: at most one operator, exclusion wins\n$prefix = $exclude ? '-' : ($require ? '+' : '');\n$query = $prefix.$term;","handlingStrategy":"validation","validationCode":"// Collapse stacked operators before building queries\n$term = ltrim($term, '+-');\n$term = $operator.$term; // $operator is '' , '+' or '-' only","typeGuard":"function hasValidOperatorSequence($q) { return !preg_match('/(^|\\s)[+-]{2,}/', $q) && !preg_match('/(:){2,}/', $q); }","tryCatchPattern":"try {\n  $result = $compiler->compileFunctionQuery($tokens);\n} catch (PhutilSearchQueryCompilerSyntaxException $ex) {\n  return array('__invalid__' => $ex->getMessage()); // caller shows it inline\n}","preventionTips":["Never concatenate optional operator prefixes","Document the query mini-language where users type queries","Fuzz-test query builders with random operators in unit tests (see PhutilSearchQueryCompilerTestCase)"],"tags":["phabricator","search","query-syntax","operator-validation","ferret"],"backgroundTag":"invalid-operator-sequence","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}