W3docs

preg_last_error()

Learn how PHP's preg_last_error() reports the error code from the last PCRE call, with error constants, preg_last_error_msg(), and examples.

Introduction

Regular expressions are a powerful tool for manipulating and searching strings in PHP. Occasionally, regex operations fail due to invalid patterns or engine limits. The preg_last_error() function helps identify these failures by returning the error code from the last PCRE function call.

Syntax

preg_last_error(): int

The function takes no arguments. It returns an integer constant describing what went wrong during the last PCRE function call — such as preg_match(), preg_match_all(), preg_replace(), or preg_split(). If the last call succeeded, it returns PREG_NO_ERROR (0).

Why you need it

PCRE functions are unusual: when they fail, they do not throw an exception. Instead, preg_match() returns false (not 0 — that means "no match"), and preg_replace() returns null. These return values tell you that something failed, but not why. preg_last_error() fills the gap by reporting the underlying reason.

That is why you must compare with === rather than a loose ==: 0 (no match) and false (error) both look "falsy", but they mean very different things.

Error constants

preg_last_error() returns one of these integer constants. The numeric values are shown for reference, but you should always compare against the named constant.

ConstantValueMeaning
PREG_NO_ERROR0No error — the last operation succeeded.
PREG_INTERNAL_ERROR1An internal PCRE error (often a malformed pattern).
PREG_BACKTRACK_LIMIT_ERROR2The pattern hit the pcre.backtrack_limit.
PREG_RECURSION_LIMIT_ERROR3The pattern hit the pcre.recursion_limit.
PREG_BAD_UTF8_ERROR4The subject is not valid UTF-8 (with the u modifier).
PREG_BAD_UTF8_OFFSET_ERROR5The offset did not match the start of a valid UTF-8 code point.
PREG_JIT_STACKLIMIT_ERROR6The pattern exhausted the JIT stack limit.

Since PHP 8.0, preg_last_error_msg() returns the same information as a human-readable string, which is handy for logging.

Triggering and reading an error

A common real-world failure is catastrophic backtracking, where a poorly written pattern forces the engine to try an enormous number of paths and trips the backtrack limit. The example below lowers pcre.backtrack_limit so the failure is reproducible, then inspects the result.

<?php

// Lower the limit so the failure is easy to reproduce.
ini_set('pcre.backtrack_limit', '100');

$pattern = '/(\w+)*$/';            // nested quantifier — backtracks heavily
$string  = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaa!';

$result = preg_match($pattern, $string, $matches);

if ($result === false) {
    echo 'preg_match() failed!' . PHP_EOL;
    echo 'Error code: ' . preg_last_error() . PHP_EOL;
    echo 'Error message: ' . preg_last_error_msg() . PHP_EOL;

    if (preg_last_error() === PREG_BACKTRACK_LIMIT_ERROR) {
        echo 'The pattern was too expensive to evaluate.' . PHP_EOL;
    }
} elseif ($result === 1) {
    echo 'Match found.' . PHP_EOL;
} else {
    echo 'No match.' . PHP_EOL;
}

Output:

preg_match() failed!
Error code: 2
Error message: Backtrack limit exhausted
The pattern was too expensive to evaluate.

The error code 2 is PREG_BACKTRACK_LIMIT_ERROR. Crucially, the if ($result === false) check is what tells us a real error occurred — a 0 here would simply mean the pattern did not match.

Detecting invalid UTF-8 input

When you use the u (unicode) modifier on a string that is not valid UTF-8, PCRE bails out and sets PREG_BAD_UTF8_ERROR:

<?php

$result = preg_match('/./u', "\x80");   // \x80 is not a valid UTF-8 sequence

if ($result === false && preg_last_error() === PREG_BAD_UTF8_ERROR) {
    echo 'Invalid UTF-8 input: ' . preg_last_error_msg();
}
// Invalid UTF-8 input: Malformed UTF-8 characters, possibly incorrectly encoded

This is a frequent source of silent bugs when processing user-submitted data, so guarding against it is good practice.

Common gotchas

  • Check it immediately. preg_last_error() reflects only the most recent PCRE call. Any later regex call overwrites it, so read it right after the operation you care about.
  • false vs 0. Always use ===. preg_match() returns 0 for "no match" and false for an error — they are not interchangeable.
  • preg_replace() failures. When preg_replace() returns null, it is also worth calling preg_last_error() to learn why.

Conclusion

preg_last_error() turns an opaque false return into an actionable reason, making it essential for debugging regular expressions in PHP. By comparing return values with === and inspecting the error code (or preg_last_error_msg()), you can cleanly separate engine failures from simple non-matches. For the functions whose failures it reports, see preg_match(), preg_replace(), and preg_split().

Practice

Practice
What does the 'preg_last_error' function in PHP do?
What does the 'preg_last_error' function in PHP do?
Was this page helpful?