Hi,

On Thu, Apr 2, 2026 at 11:18 AM Pierre Joye <[email protected]> wrote:

> Hi Tim, Jakub,
>
> On Tue, Mar 31, 2026 at 5:52 PM Tim Düsterhus <[email protected]> wrote:
> >
> > Hi
> >
> > Am 2026-03-29 20:25, schrieb Jakub Zelenka:
> > >> For the naming of `stream_get_last_error()`: Within PHP we have both
> > >> `X_get_last_error()` and `X_last_error()`. The latter seems to be more
> > >> common and also what I would prefer here, because the `stream_get_`
> > >> prefix sounds to me like we would get something from a stream, but the
> > >> returned value is not related to a specific stream, but rather a
> > >> global.
> > >>
> > >>
> > > Good point, I changed it but because it now returns array (no linked
> > > list),
> > > it's called stream_last_errors(). I also added  stream_clear_errors for
> > > explicit clearing which might be useful in some situations.
> >
> > That both makes sense to me.
> >
> > > The RFC and the implementation is updated so please take a look!
> >
> ...
> > 3. For "StreamErrorCode::is*()"
> >
> > Can error codes fall into multiple categories or is it always a single
> > one? If it's guaranteed to be a single category, then perhaps a
> > `->getErrorCategory()` method returning a StreamErrorCodeCategory enum
> > makes more sense and allow for simpler / more efficient code when folks
> > are interested in checking for multiple different categories. Instead of
> > `$code->isNetworkError() || $code->isFileSystemError()` they can do
> > `\in_array($code->getErrorCategory(),
> > [StreamErrorCodeCategory::NetworkError,
> > StreamErrorCodeCategory::FileSystemError], true)` or use a `match()`
>
> These points actually are on the spot about what I've been trying to
> raise earlier in this thread, or they demonstrate it nicely.
>
> Suggesting a getErrorCategory() method or a StreamErrorCodeCategory
> enum to make category checks cleaner. That's a reasonable API
> improvement, in the context of what the RFC proposes in the current
> state. But it also highlights the underlying design issue: we're
> building a parallel categorization system on top of error codes, when
> the type system already provides exactly this, through exception
> subclasses, for free. That reminds a bit of the early OO's time in php
> when all we did was to wrap the legacy procedural implementation in
> dumb OO wrapper, saving, if lucky, user's keystrokes. That's not even
> the case here.
>
> The point is that a stream operation can produce errors of different
> categories and therefore the exception "cannot be reasonably
> categorised": this is how exceptions have always worked. One throws
> the primary exception, the one that caused the operation to fail, and
> chain additional context via $previous or attach it as metadata. The
> caller catches what they care about:
>
> catch (StreamNetworkException $e) {...}
>
> The exception type answers "what do I do about this?" The error chain
> answers exactly what happens, where in detail. These are different
> questions for different uses, and conflating them is what leads to the
> current design where it catches a flat StreamException and then has to
> inspect its contents to find out what kind of failure it was.
>
> getErrorCategory() suggestion would give us
> match($e->getErrors()[0]->getErrorCategory()) { ... } inside a catch
> block. That's essentially reimplementing what catch
> (StreamNetworkException $e) already does, except the type system can't
> help, static analysis can't reason about it, and it can't compose it
> with other exception handling in a codebase.
>
> The current RFC introduces exception syntax without exception
> semantics. The isFileSystemError(), isNetworkError() methods, and now
> potentially getErrorCategory(). are workarounds for the absence of a
> typed hierarchy, not features we should need in the 1st place.
>
>
Thanks for the thorough feedback. After some considering I decided not to
expose those helpers at this stage. The reason is that the current
classification is a bit uncertain and I want to have more final set of
error codes before anything like this is introduced. The current setup was
a bit random and sometimes it could go to multiple categories so there are
some decisions to be made. Also the is* methods were not the best design as
pointed out and other option should be considered. I'm also not too sure
about usefulness of categories. All of this should be decided on its own
and later.



> Since StreamException does not exist in any current PHP version, there
> is zero BC cost to making it a proper base class now. It takes more
> effort to design such additions correctly, however it would be a
> significant improvement in the long run for php's stream, beyond a
> current internal refactoring and long due cleaning :).
>
>
I don't see how it takes more effort later. There is also pretty much no BC
break even if we went if subclassing exceptions as I noted before. I think
actually exactly opposite here. If we rush it and use incorrect categories
for some errors, it will be a BC break to correct so this needs a proper
considering and this feature should be added later.

Kind regards,

Jakub

Reply via email to