{"record":{"id":"f8fdb5f78867779f","repo":"phacility/phabricator","slug":"second-regular-expression-is-invalid","errorCode":null,"errorMessage":"Second regular expression is invalid!","messagePattern":"Second regular expression is invalid!","errorType":"validation","errorClass":"HeraldInvalidConditionException","httpStatus":null,"severity":"error","filePath":"src/applications/herald/adapter/HeraldAdapter.php","lineNumber":580,"sourceCode":"        }\n        if (count($regexp_pair) != 2) {\n          throw new HeraldInvalidConditionException(\n            pht('Regular expression pair is not a pair!'));\n        }\n\n        $key_regexp   = array_shift($regexp_pair);\n        $value_regexp = array_shift($regexp_pair);\n\n        foreach ((array)$field_value as $key => $value) {\n          $key_matches = @preg_match($key_regexp, $key);\n          if ($key_matches === false) {\n            throw new HeraldInvalidConditionException(\n              pht('First regular expression is invalid!'));\n          }\n          if ($key_matches) {\n            $value_matches = @preg_match($value_regexp, $value);\n            if ($value_matches === false) {\n              throw new HeraldInvalidConditionException(\n                pht('Second regular expression is invalid!'));\n            }\n            if ($value_matches) {\n              return true;\n            }\n          }\n        }\n        return false;\n      case self::CONDITION_RULE:\n      case self::CONDITION_NOT_RULE:\n        $rule = $engine->getRule($condition_value);\n        if (!$rule) {\n          throw new HeraldInvalidConditionException(\n            pht('Condition references a rule which does not exist!'));\n        }\n\n        $is_not = ($condition_type == self::CONDITION_NOT_RULE);\n        $result = $engine->doesRuleMatch($rule, $this);","sourceCodeStart":562,"sourceCodeEnd":598,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/herald/adapter/HeraldAdapter.php#L562-L598","documentation":"The second half of regexp-pair evaluation: once the key regexp matches a dictionary key, the adapter runs @preg_match($value_regexp, $value); if that returns false the value pattern is invalid and HeraldInvalidConditionException('Second regular expression is invalid!') is thrown. Note it fires only after a key matched, so a broken second pattern can lurk until a key first matches.","triggerScenarios":"The second (value) element of the JSON pair is an invalid PCRE pattern (missing delimiters, bad syntax) and evaluation reaches a dictionary entry whose key matches the first pattern.","commonSituations":"Same as other invalid-pattern cases: API-written values, delimiter or escaping mistakes, copy-pasted patterns from other regex dialects.","solutions":["Validate the second pattern standalone: php -r 'var_dump(@preg_match(\"/value-pattern/\", \"x\"));' must not return false.","Fix delimiters/syntax and re-save the rule.","When generating pairs programmatically, validate both patterns with @preg_match(...) === false checks before saving."],"exampleFix":"// before (value regexp missing delimiter)\n[\"/^build-/\", \"nightly$\"]\n\n// after\n[\"/^build-/\", \"/nightly$/\"]","handlingStrategy":"validation","validationCode":"// Validate the SECOND (value) regexp of the pair before saving:\nif (@preg_match($value_regexp, '') === false) {\n  // value regexp is invalid - fix before saving the condition\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate both elements of the pair; the second pattern only fails lazily once a key matches.","Use the same delimiter style for both patterns and test them in php -r before saving."],"tags":["herald","regex","pcre","phabricator"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}