Hi
On 2026-09-07 13:58, Robert Humphries wrote:
Arguably this specific case is a bit debatable, but as the author of
the
throwable policy RFC, I believe that it is at least violated in
spirit.
The goal of the throwable policy generally, and also with regard to
that
specific paragraph is to allow reliably handling groups of errors
without needing to wrap every individual statement into its own
try-catch block.
Obviously you wrote the policy and so are best placed to interpret it
(and I am not a core developer / person with voting rights); however I
agree with the angle Osama is coming from here - I wouldn't say this
is an error that is (always) part of the same group. There wasn't any
error in the call to `preg_replace_callback` itself (or any of its
functionality) - the error was in a way during the processing of the
Yes, I agree that this case is not entirely clear-cut - and it's good
we're having this discussion now.
If I have understood the other example correctly, this contradicts
quite significantly with the CSPRNG throwing an Exception that
`RandomException` contains - as the failure is a core issue within the
function call itself as opposed to logic that occurs in userland.
I think there might be a misunderstanding based on how you phrased that
paragraph. To provide a more specific example:
Consider I have a session implementation that uses Redis as its session
storage backend. Session IDs need to be created using secure randomness,
i.e. using the CSPRNG. Both the Redis backend and the CSPRNG can
theoretically fail. As a user when create a new session I want to be
able to just catch (SessionInitializedFailedException) and not care
about whether the CSPRNG or the Redis connection failed, and I might not
even know if it's Redis, Memcache, a File System or a MySQL database.
Thus any underlying issues must be wrapped into a session-specific
exception.
preg_replace_callback() is different in that I explicitly pass in a
callback and thus I'm technically in full control over the code that is
being executed and I can theoretically know what exceptions could
possibly be thrown and might intentionally want to handle them
explicitly. On the other hand, failing to execute the callback means
that the replacing operation failed, no further callbacks will be called
and preg_replace_callback() will not return anything - and that is a
“running this regex failed” a.k.a. PregException situation to me.
If anything, I would argue that under the policy this should go the
other way and become `PregError`:
The Error hierarchy MUST NOT be used for errors that are expected to
be thrown (and caught) during normal operation of a PHP program.
In terms of the possible errors that could occur, I would expect at
least `PREG_INTERNAL_ERROR`, `PREG_BAD_UTF8_ERROR` &
`PREG_JIT_STACKLIMIT_ERROR` to be code errors that require a developer
to need to correct their code (as my understanding of these would be
that the pattern is invalid, or not quoted correctly, etc. Although
`PREG_BACKTRACK_LIMIT_ERROR` & `PREG_RECURSION_LIMIT_ERROR` are more
likely to occur based on user input, then the limit for both is
controlled by an ini setting - so again, this likely isn't something I
would say is expected to be thrown and caught during normal operation
of a PHP program. The final error (`PREG_BAD_UTF8_OFFSET_ERROR`) I
_think_ would still likely need a code change to fix it occurring -
although I have only done a quick Google to see _when_ it may occur.
This is a good point. I agree that things like pattern compilation
failures should be a PregError, since this is a clear programmer error
and regular expressions are not supposed to be untrusted inputs. For the
error error situations I would need to check as well if they are
expected during regular operation or not. The backtrack or recursion
limits I can see being caught intentionally to provide better error
messages to a user (thus PregException).
Best regards
Tim Düsterhus