Signature
preg_last_error_msg(): stringPurpose
PHP's preg_* functions signal many runtime problems by returning false or null rather than throwing an exception. A false result alone does not say why the call failed. preg_last_error_msg() fills that gap: it returns a human-readable description of the status left by the most recent PCRE call. It is the text counterpart of preg_last_error(), which returns an integer code.
Use it when you log failures, build diagnostics, or wrap regex calls in code that must report what went wrong.
Signature
The function is documented as available from PHP 8.
Parameters and defaults
There are no parameters, so there are no defaults. The function always reports on the last PCRE function call in the current request.
Return value and failure cases
The function always returns a string. If the last PCRE call finished without a problem, the string is No error. Otherwise it describes the problem. Typical messages include:
Internal errorBacktrack limit exhaustedRecursion limit exhaustedMalformed UTF-8 characters, possibly incorrectly encodedJIT stack limit exhausted
The function never throws and never returns false. The failure being reported belongs to the earlier preg_* call, not to preg_last_error_msg() itself.
Example 1: a successful match
After a call that completes normally, the message is No error. This includes a call that simply finds no match, because not matching is not an error.
preg_match('/\d+/', 'order 42');
echo preg_last_error_msg(), "\n";No error
Example 2: invalid UTF-8 input
With the u modifier, the subject must be valid UTF-8. The bytes C3 28 are not, so the match fails and returns false. The message tells you the reason.
$result = preg_match('/./u', "\xC3\x28");
echo json_encode([$result, preg_last_error_msg()], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";[false,"Malformed UTF-8 characters, possibly incorrectly encoded"]
Example 3: a small wrapper that reports status
A wrapper keeps the result and the message together. It reads the message immediately after the call, before any other regex function can overwrite it.
function tryMatch(string $pattern, string $subject): array
{
$result = preg_match($pattern, $subject);
return ['result' => $result, 'message' => preg_last_error_msg()];
}
echo json_encode(tryMatch('/./u', "\xC3\x28"), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
echo json_encode(tryMatch('/./u', 'ok'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"result":false,"message":"Malformed UTF-8 characters, possibly incorrectly encoded"}
{"result":1,"message":"No error"}
The second call shows that the status is replaced by each new PCRE call: the earlier UTF-8 failure does not linger.
Edge cases
- Only the latest call counts. Each
preg_*call replaces the stored status. If you run two regex calls and then read the message, you learn only about the second one. - No match is not an error.
preg_match()returning0still leavesNo error. - Resource limits depend on configuration. The manual's example uses a pattern that backtracks heavily and reports
Backtrack limit exhausted. Whether a given pattern hits a limit can depend on PCRE settings such aspcre.backtrack_limitand on whether the JIT is active, so do not rely on one pattern to trigger a specific message across servers. - Compile problems differ. A pattern that cannot be compiled is a different kind of failure from a runtime limit, and PHP may also raise a warning for it. Treat the message as one source of information, not the only one.
- Calling it before any regex call. If no PCRE function has run, there is no error to report, so expect
No error.
Common mistakes
- Checking the message instead of the return value. A string such as
No errordoes not prove your pattern matched. Check the return value ofpreg_match()first, using strict comparison withfalse, and consult the message only when a failure is indicated. - Reading the message too late. Calling another
preg_*function, or code that calls one internally, before reading the status overwrites it. - Using
== falseonpreg_match(). Because0also equalsfalseloosely, a plain no-match gets treated like a failure. Use=== false. - Parsing the message text. The strings are meant for people. If your code needs to branch on the kind of failure, compare the integer from
preg_last_error()with thePREG_*_ERRORconstants. - Assuming it clears itself on demand. You cannot reset the status directly; it only changes when another PCRE call runs.
Related functions
preg_last_error()returns the numeric code for the same status.preg_match(),preg_match_all(),preg_replace()andpreg_split()are the calls whose status it reports.json_last_error_msg()follows the same pattern for the JSON functions.
Recap
preg_last_error_msg() takes no arguments and returns a string describing the last PCRE call. No error means that call completed normally, even with no match. Check the return value of the regex function first, read the message right away, and use preg_last_error() when code must branch on a specific failure.
Tested examples
preg_match('/\d+/', 'order 42');
echo preg_last_error_msg(), "\n";
No error
$result = preg_match('/./u', "\xC3\x28");
echo json_encode([$result, preg_last_error_msg()], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
[false,"Malformed UTF-8 characters, possibly incorrectly encoded"]
function tryMatch(string $pattern, string $subject): array
{
$result = preg_match($pattern, $subject);
return ['result' => $result, 'message' => preg_last_error_msg()];
}
echo json_encode(tryMatch('/./u', "\xC3\x28"), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
echo json_encode(tryMatch('/./u', 'ok'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
{"result":false,"message":"Malformed UTF-8 characters, possibly incorrectly encoded"}
{"result":1,"message":"No error"}