[PHP-DEV] [RFC] [Discussion] PREG_THROW_ON_ERROR

[email protected] (Osama Aldemeery) Tue, 28 Jul 2026 03:56:51 +0300
Newsgroups php.internals
Message-ID <CABE7Eu-to87bSEjBUDOAmR1BkOX=WqyC3GQFdwFdQB2ahLaicw@mail.gmail.com>
--00000000000018c1070657a1516f
Content-Type: text/plain; charset="UTF-8"

Hi all,

Following the earlier pre-RFC discussion (
https://news-web.php.net/php.internals/131783), I've written this up as a
proper RFC: https://wiki.php.net/rfc/preg_throw_on_error

Short version:

a `PREG_THROW_ON_ERROR` flag you pass to any `preg_*()` call, so a PCRE
error throws a `\PregException` you can catch
instead of a warning plus a `false` / `null` you have to notice and then
chase through `preg_last_error()`.
Same thing `JSON_THROW_ON_ERROR` and `FILTER_THROW_ON_FAILURE` already do
for their functions.
It's opt-in, so nothing changes without the flag.

The flag only changes how an error is delivered. A call does exactly the
same thing with it or without it, byte for byte.
The only difference is that at the end, any error the call would have
recorded is additionally thrown, carrying the same code and
message `preg_last_error()`/`preg_last_error_msg()` would report.

For array arguments that means the flag mirrors `preg_last_error()`...it
throws whatever error the same call leaves there,
which for `preg_replace()` over an array is the last-processed entry, not
the first. (In the pre-RFC I'd floated throwing on the first failing
element instead).
Whether the `preg_*()` functions should stop at the first failing entry is
a separate question about those functions, one that applies with or without
the flag, so it's out of scope here.

The exception name is settled from the pre-RFC as `\PregException` (thanks
Tim) and the flag as `PREG_THROW_ON_ERROR`.

Target is the next feature release after 8.6 since 8.6's beta1 is too close
for this to conclude discussion and a vote in time.

I also saw Larry's note asking to hold new business that isn't targeting
8.6 until the freeze rush is over.
This won't catch 8.6, so I'm not asking for any priority while the freeze
is on. But the pre-RFC discussion was already open before
Larry's note, so I'd rather keep it ticking over quietly than restart it in
September.
If someone prefers I park it until then, please say so and I will.

Implementation and tests: https://github.com/php/php-src/pull/22797

Thanks,
Osama

--00000000000018c1070657a1516f
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hi all,<br><br>Following the earlier pre-RFC discussion (<=
a href=3D"https://news-web.php.net/php.internals/131783">https://news-web.p=
hp.net/php.internals/131783</a>), I&#39;ve written this up as a proper RFC:=
 <a href=3D"https://wiki.php.net/rfc/preg_throw_on_error">https://wiki.php.=
net/rfc/preg_throw_on_error</a><br><br>Short version:<br><br>a `PREG_THROW_=
ON_ERROR` flag you pass to any `preg_*()` call, so a PCRE error throws a `\=
PregException` you can catch<br>instead of a warning plus a `false` / `null=
` you have to notice and then chase through `preg_last_error()`.<br>Same th=
ing `JSON_THROW_ON_ERROR` and `FILTER_THROW_ON_FAILURE` already do for thei=
r functions.<br>It&#39;s opt-in, so nothing changes without the flag.<br><b=
r>The flag only changes how an error is delivered. A call does exactly the =
same thing with it or without it, byte for byte.<br>The only difference is =
that at the end, any error the call would have recorded is additionally thr=
own, carrying the same code and<br>message `preg_last_error()`/`preg_last_e=
rror_msg()` would report.<br><br>For array arguments that means the flag mi=
rrors `preg_last_error()`...it throws whatever error the same call leaves t=
here,<br>which for `preg_replace()` over an array is the last-processed ent=
ry, not the first. (In the pre-RFC I&#39;d floated throwing on the first fa=
iling element instead).<br>Whether the `preg_*()` functions should stop at =
the first failing entry is a separate question about those functions, one t=
hat applies with or without the flag, so it&#39;s out of scope here.<br><br=
>The exception name is settled from the pre-RFC as `\PregException` (thanks=
 Tim) and the flag as `PREG_THROW_ON_ERROR`.<br><br>Target is the next feat=
ure release after 8.6 since 8.6&#39;s beta1 is too close for this to conclu=
de discussion and a vote in time.<br><br>I also saw Larry&#39;s note asking=
 to hold new business that isn&#39;t targeting 8.6 until the freeze rush is=
 over.<div>This won&#39;t catch 8.6, so I&#39;m not asking for any priority=
 while the freeze is on. But the pre-RFC discussion was already open before=
<br>Larry&#39;s note, so I&#39;d rather keep it ticking over quietly <span =
aria-invalid=3D"grammar" class=3D"Lm ng" style=3D"border-style:none;backgro=
und:none">than</span> restart it in September.<br>If someone prefers I park=
 it until then, please say so and I will.<br><br>Implementation and tests: =
<a href=3D"https://github.com/php/php-src/pull/22797">https://github.com/ph=
p/php-src/pull/22797</a><br><br>Thanks,<br>Osama</div></div>

--00000000000018c1070657a1516f--