preg_last_error_msg

Returns a human-readable message for the last PCRE regex error.

Signature
preg_last_error_msg(): string
  • Added in PHP 8.0

Return value

stringThe message for the last PCRE error, or the string "No error" if the last execution succeeded.

Like the numeric code, it is reset by the next preg_* call, and it describes a compile failure only as the generic "Internal error" — a broken pattern sets PREG_INTERNAL_ERROR, so the actual compile diagnostic is in the E_WARNING, not in this message.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Attach a real reason to an exception when a validation regex returns false
  • Log why a preg_replace over a large imported document produced null
  • Report the PCRE limit that was hit when a pattern behaves differently in production

Frequently asked questions

What PHP version added preg_last_error_msg?

PHP 8.0. On PHP 7 and earlier you have to map the integer from preg_last_error() to a message yourself.

What does preg_last_error_msg return when there is no error?

The literal string "No error". Because that is truthy, test for success with preg_last_error() === PREG_NO_ERROR rather than with the message.

Does preg_last_error_msg tell me my pattern has a syntax error?

Not the details. A pattern that fails to compile raises an E_WARNING with the compile error and makes this function report "Internal error" (PREG_INTERNAL_ERROR) — not "No error". Verified on PHP 8.3: after @preg_match('/[/', 'x'), preg_last_error_msg() returns "Internal error". Only the E_WARNING tells you which syntax error it was.

More examples

Turning a silent failure into an exception

The catch block prints 'regex: Backtrack limit exhausted'. The check on preg_last_error() is what decides there was a failure — the message is only there to explain it.

Example · php
<?php
function matchOrFail(string $pattern, string $subject): int {
    $r = preg_match($pattern, $subject);
    if ($r === false || preg_last_error() !== PREG_NO_ERROR) {
        throw new RuntimeException('regex: ' . preg_last_error_msg());
    }
    return $r;
}

try {
    matchOrFail('/(?:\D+|<\d+>)*[!?]/', 'foobar foobar foobar');
} catch (RuntimeException $e) {
    echo $e->getMessage(), "\n";
}

Why the message alone is not a condition

After a successful match the message is the non-empty string 'No error', so casting it to bool gives true. Only the last line is a correct success test.

Example · php
<?php
preg_match('/ok/', 'ok');

var_dump(preg_last_error_msg());          // string(8) "No error"
var_dump((bool) preg_last_error_msg());   // bool(true)  <- trap
var_dump(preg_last_error() === PREG_NO_ERROR);

Invalid UTF-8 subject

preg_match returns false and the message describes malformed UTF-8 in the subject, with the numeric code PREG_BAD_UTF8_ERROR (4). Removing the u modifier makes the same call succeed, because the bytes are then matched without UTF-8 validation.

Example · php
<?php
$bad = "\xB1\x31";

var_dump(preg_match('/./u', $bad));
echo preg_last_error_msg(), "\n";
echo preg_last_error(), "\n";

Discussion

  • Be the first to comment on this lesson.