sebastianbergmann/phpunit · error · PHPUnit\Framework\Exception

Invalid expected exception message regular expression given:

Error message

Invalid expected exception message regular expression given: %s

What it means

The ExceptionMessageMatchesRegularExpression constraint backs expectExceptionMessageMatches(): it runs @preg_match($this->regularExpression, $message). When PCRE rejects the pattern (preg_match returns false rather than 0 or 1), it throws Framework\Exception('Invalid expected exception message regular expression given: <pattern>'). The failure is in the pattern itself, not in the tested code.

Source

Thrown at src/Framework/Constraint/Exception/ExceptionMessageMatchesRegularExpression.php:53

    }

    /**
     * Evaluates the constraint for parameter $other. Returns true if the
     * constraint is met, false otherwise.
     *
     * @throws \PHPUnit\Framework\Exception
     * @throws Exception
     */
    protected function matches(mixed $other): bool
    {
        if (!is_string($other)) {
            return false;
        }

        $match = @preg_match($this->regularExpression, $other);

        if ($match === false) {
            throw new \PHPUnit\Framework\Exception(
                sprintf(
                    'Invalid expected exception message regular expression given: %s',
                    $this->regularExpression,
                ),
            );
        }

        return $match === 1;
    }

    /**
     * Returns the description of the failure.
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     */
    protected function failureDescription(mixed $other): string
    {

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Make the pattern a valid PCRE expression with matching delimiters, e.g. '/timeout after \d+ seconds/i'
  2. If you only need a literal check, use expectExceptionMessage($substring) instead — no regex involved
  3. Test dynamic patterns before use: if (@preg_match($pattern, '') === false) { /* fix pattern */ }
  4. Simplify the regex; a long anchored pattern is more likely to contain a syntax slip than a short one

Example fix

// before
$this->expectException(TimeoutException::class);
$this->expectExceptionMessageMatches('timeout after \d+ seconds'); // no delimiters

// after
$this->expectException(TimeoutException::class);
$this->expectExceptionMessageMatches('/timeout after \d+ seconds/i');
Defensive patterns

Strategy: validation

Validate before calling

$pattern = '/timeout after \d+ seconds/i';
if (@preg_match($pattern, '') === false) {
    throw new InvalidArgumentException("Invalid regex: {$pattern}");
}

Type guard

static function isValidPcrePattern(string $pattern): bool
{
    return @preg_match($pattern, '') !== false;
}

Try / catch

try {
    $this->expectExceptionMessageMatches($pattern);
} catch (\PHPUnit\Framework\Exception $e) {
    if (str_contains($e->getMessage(), 'Invalid expected exception message regular expression')) {
        // fix the pattern (delimiters/modifiers) before re-running
    }
    throw $e;
}

Prevention

When it happens

Trigger: Calling $this->expectExceptionMessageMatches($pattern) with a malformed PCRE pattern: missing delimiters ('SomeMessage' with no /.../), unbalanced delimiters, an unknown trailing modifier, or invalid UTF-8 sequences with the u modifier.

Common situations: Upgrading from PHPUnit 9's expectExceptionMessageRegExp where delimiter habits differed; copy-pasting substrings instead of full patterns; patterns assembled dynamically where a fragment is empty or malformed.

Related errors


AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23). Data as JSON: /api/errors/b4e6aa2629298b3d. Report an issue: GitHub.