Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130201 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 82AB51A0118 for ; Fri, 27 Feb 2026 22:21:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1772230884; bh=toV/CWZ/LOWt04GvifFMm3iumFECkrzHXK2HQTb24CE=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=UTnPLS5VketDaKRJhw7QdMDjPlUb74/0Br59u4HMpaYH+VxQdypmq51G50sFyZSB2 KbNsgYc9GKpYi+SNyuFZSRmDraB2XVlv9P8f1VkaNeLC5YfMpoWjsECE+YylT6KSNQ 8ZDm3nuJt6Mv4bQoaSrZ1imX/UGFPkcLdwRRzN488qylXoXPWL3kHwi7rdk0/M3+zO qsmDd45dej2DgqRnk6Txij2TqVW3RE29w8MMlpxivWNgTWJvSO2s2JRWkOfpv3ADn0 kljFctYwQQTXF0T+TkxXftGsVrNG/svG0lKzAU9NzGcxSnhwW1WBjnJTgxuflFrJfV B0tQO/entWHwQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id C41801801E7 for ; Fri, 27 Feb 2026 22:21:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: * X-Spam-Status: No, score=1.7 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_50, DMARC_NONE,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-oo1-f43.google.com (mail-oo1-f43.google.com [209.85.161.43]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 27 Feb 2026 22:21:22 +0000 (UTC) Received: by mail-oo1-f43.google.com with SMTP id 006d021491bc7-66f3e7d9eccso1716248eaf.1 for ; Fri, 27 Feb 2026 14:21:17 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1772230877; cv=none; d=google.com; s=arc-20240605; b=Mz7Vmu2qOwXUH8IcTmfjHtO0mOknjVhnqpf4InwmTDij4IKinzs/CQkCp9hU98g43u 95JNnLEB5/NIrnKmIhDuHUnzYAIjIHGpn8CUz4lcTNDr0aUgij2sdGjxaB1tm/RN2URD s4grHT6jy5prvpXrUbLc8xgn8wOWuf8OyFfC0soJv3BvyVudCmkvOYSkzGFZ9y8164Im xonqK3scPBqx+B06n3gBygzZvwNT/PRLfAhfPqr60u/NSg4uxEwXiFmuCDBMDvy7m0rt t3O2MQ2ug+XJmql5m2F0dBVlv21BvMAjckMD/6GZJkpfWspOaBKP27rS67WJjafcTJGh X5hg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version; bh=toV/CWZ/LOWt04GvifFMm3iumFECkrzHXK2HQTb24CE=; fh=+Olut09awgBB5IxEO9xPIU68miEei4hvoITNrzLyq5c=; b=iOUDzQbvVHrwcYr9cxPgFCRoHIa/VAOOKo1zkfSw22Q2Vy3dRLH/o5n6efKd7rbAs7 SKwSnhVUnjUZXhnB+wXDJxnX/qOLfD5GUwEfhpl7SIQ76mfxpWlgg7ltTRZU/Igr1/w3 c5fgDp66QbW+FkCv37L2zjw1+nrWM5RFbu1WUY7ymMiNXOnN58JN0B8L8fjOaLWL5Rc+ GJfPuP5jLpcO+a7fS3T12oiPxXNUgx2YxbLaMkV5GirORbS28IaknSvZT5o4HG8q5Bko SBF0xL+aPcbEIFoWJSSqh5Jb0Oy3XZbgnt38lM6hwdiGvx5GmFWO784Gj/XqPDond6e3 WKzQ==; darn=lists.php.net ARC-Authentication-Results: i=1; mx.google.com; arc=none X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772230877; x=1772835677; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=toV/CWZ/LOWt04GvifFMm3iumFECkrzHXK2HQTb24CE=; b=oFZYgMYZ0tGRJ+3iPpkrZ11w0Hhk4J9Xwa6g8fQmjaICt5FSE8ZnDrHAbmVipwYM6B 9iE2s49NBZqdzv8t62jtK+FrmLY28OzVVAoH6F6EkIcx25AcAqgCoBvhxOwGUOskBTjJ 6t78FnItJbZ2cqaLh9a/DUMrF5hzGTVjAabbkFkeW7zbOYT2H40dkjyVsou2C2PRCRFU SbrCg1+ZbvO2OhwAZmj6wsZZTYXX9uPoR2SLoTP92KIcQCloMNk2+JEASI3S08elcDOz r5JOev0FIHSAgCqaqjxOALppkErcVNk93PWj3jNNLN9+imDya9hsJ1EblUS87POsofnv drQQ== X-Gm-Message-State: AOJu0YzrwaP12jYyim9j888Fmb60+1yo7weQaPJiCYA5J2Ie+NybGrCW GE73EtZPlUInFNh894EytTEK971IlBRmUfSDR/41+8rTGxs0eGhAgwePXuDLPphC6Sdx8DpA+Me BSjPyYnUgMA8CNBeYFi9KZMBlQwY8s7M= X-Gm-Gg: ATEYQzxUoFO5RRLQdzMUnzqNj3hBRaSMw3MtkbrpctWzKXIDCSiakVXgX3vSO/9VpMn qqZRaMwX0WB76f844vwWiCS09sG7HexAuh9KdDDciO7pDWzDU6oLyqOqdz+6AvwDo+t2YPBiKph kjxNEMsaZ6r4NEkRFmbXBF6cZGIfYgmiZkuNkgRkUerpcBQ8tsaPZKOyuljo0ItXteMoQBUD78T 2zeWUVP4U1ajmrx4UN5wCqgcy/DYMYLNczTT2oENhoyOR2ut+YfhYk/QszXEWG7KtUvyk5tYfm7 PRXpF+s= X-Received: by 2002:a05:6820:162c:b0:676:da74:842b with SMTP id 006d021491bc7-679fae4648bmr2786456eaf.28.1772230876658; Fri, 27 Feb 2026 14:21:16 -0800 (PST) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 27 Feb 2026 23:21:05 +0100 X-Gm-Features: AaiRm53-CO_kDsBz5WS8olIBro4bQWRKxxReozvAPIpIJdnp3RShi5LPEk-lmZA Message-ID: Subject: Re: [PHP-DEV] Re: [RFC] Stream Error Handling Improvements To: Nicolas Grekas Cc: PHP internals list Content-Type: multipart/alternative; boundary="000000000000dd0068064bd5a72f" From: bukka@php.net (Jakub Zelenka) --000000000000dd0068064bd5a72f Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi, On Wed, Feb 25, 2026 at 7:11=E2=80=AFPM Nicolas Grekas wrote: > Hi Jakub, > > I would like to introduce a new stream error handling RFC that is part of >>> my stream evolution work (PHP Foundation project funded by Sovereign Te= ch >>> Fund) : >>> >>> https://wiki.php.net/rfc/stream_errors >>> >>> >> I just updated implementation and RFC to version 2.1 which addresses the below issues. > As there has not been much discussion and keeping the patch up to date is >> a slight pain, I plan to open voting on Friday (27/02/26) evening or >> Saturday (28/02/26) morning unless some changes are required ofc. >> > > The update means that the vote will not happen in the next two weeks... > Thanks for the reminder! I discussed this with others and we raised the > following points: > > 1. StreamErrorCode::None: do we need it? > > Having an enum case representing "no error" feels a bit off to me. If an > API needs to express the absence of an error, would,'t StreamErrorCode|nu= ll > be more idiomatic? StreamErrorCode::None seems like a nullable value > disguised as an enum case, and it means callers always have to guard > against it, which somewhat defeats the purpose of using an enum. Am I > missing a use case where ::None is genuinely needed? > As I removed the enum this is no longer issue. I kept none as constant for comparing as it might be useful. > > 2. StreamError::$next =E2=80=94 is the naming intentional? > > Since stream_get_last_error() returns the most recent error and the chain > travels backwards through time, $next seems to point to the previous erro= r > chronologically. Would something like $previous (echoing > Throwable::getPrevious()) work better, or is the current naming deliberat= e? > > I checked this one and realised that $next is actually better because it's better to keep the first error which for streams is really the useful one. The follow up errors (if any - most of the time there's just one) are most of the time not that useful but might add a bit more context so that's why they are chained. I added this reasoning to the RFC. > 3. Should StreamErrorCode really be an enum? > > The RFC lists in its "Future Scope" section: "Extension-specific error > ranges - Reserved ranges for extensions to define custom error codes." > > This gave us pause. Enums in PHP are intentionally a closed, finite type: > their value is precisely that "invalid states become unrepresentable." If > extensions can define custom error codes at runtime, the set of possible > values would depend on which extensions are installed, and the type would > no longer be truly enumerable. > Larry touches on this exact tension in this post: when the value space > needs to be open or user-extensible, an enum is the wrong tool. > https://www.garfieldtech.com/blog/on-the-use-of-enums#open-type > > I'd also expect the built-in list of codes to keep growing over time as > more wrappers and edge cases are covered; which is another hint the domai= n > may not be fixed. > > Would a set of integer constants (possibly grouped in a class or > interface) be appropriate? It would be more honest about the open-ended > nature of the value space while still allowing meaningful comparisons, > without creating false expectations of exhaustiveness. > > I changed it to the StreamError class constants and also move the is*Error functions there. > 4. Using stream_context_set_default to change error_mode looks hazardous > > The RFC includes an example where stream_context_set_default is used to > set error_mode to StreamErrorMode::Exception globally. I'm worried about > the ecosystem impact here: if any library or application bootstrap does u= se > this, then existing packages using the common > @file_get_contents('maybe_existing_file') idiom could e.g. suddenly throw > uncaught exceptions, breaking behavior their authors had deliberately > chosen. This feels like a significant compatibility hazard for code that > doesn't control its full execution environment. > > Would it be worth restricting error_mode (and possibly the other new > options) so that they can only be set via per-call contexts, not via > stream_context_set_default? > > I added that restriction and also added context to some stream functions so it can be set explicitly. There will be more function extended in the future if this passes. Hope it's ok now! If there's anything else, please let me know. Cheers Jakub --000000000000dd0068064bd5a72f Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi,

On Wed, Feb 25, 2026 at 7:11= =E2=80=AFPM Nicolas Grekas <nicolas.grekas+php@gmail.com> wrote:
Hi Jakub,

=
I would like to introduce a new strea= m error handling RFC that is part of my stream evolution work (PHP Foundati= on project funded by Sovereign Tech Fund) :

https://wiki.php.net/rfc/strea= m_errors



I just updated = implementation and RFC to version 2.1 which addresses the below issues.
=C2=A0
As= there has not been much discussion and keeping the patch up to date is a s= light pain, I plan to open voting on Friday (27/02/26) evening or Saturday = (28/02/26) morning unless some changes are required ofc.
<= /blockquote>


The= update means that the vote will not happen in the next two weeks...
<= div>=C2=A0
Thanks for the reminder= ! I discussed this with others and we raised the following points:

1. StreamErrorCode::None: do we need it?

Having an = enum case representing "no error" feels a bit off to me. If an AP= I needs to express the absence of an error, would,'t StreamErrorCode|nu= ll be more idiomatic? StreamErrorCode::None seems like a nullable value dis= guised as an enum case, and it means callers always have to guard against i= t, which somewhat defeats the purpose of using an enum. Am I missing a use = case where ::None is genuinely needed?


As I removed the enum this is no longer is= sue. I kept none as constant for comparing as it might be useful.
=C2=A0

2. StreamError::$next =E2=80=94 is= the naming intentional?

Since stream_get_last_error() returns the m= ost recent error and the chain travels backwards through time, $next seems = to point to the previous error chronologically. Would something like $previ= ous (echoing Throwable::getPrevious()) work better, or is the current namin= g deliberate?


I c= hecked this one and realised that $next is actually better because it's= better to keep the first error which for streams is really the useful one.= The follow up errors (if any - most of the time there's just one) are = most of the time not that useful but might add a bit more context so that&#= 39;s why they are chained. I added this reasoning to the RFC.
=C2= =A0
3. Should StreamErrorCode really be an enu= m?

The RFC lists in its "Future Scope" section: "Exte= nsion-specific error ranges - Reserved ranges for extensions to define cust= om error codes."

This gave us pause. Enums in PHP are intention= ally a closed, finite type: their value is precisely that "invalid sta= tes become unrepresentable." If extensions can define custom error cod= es at runtime, the set of possible values would depend on which extensions = are installed, and the type would no longer be truly enumerable.
Larry t= ouches on this exact tension in this post: when the value space needs to be= open or user-extensible, an enum is the wrong tool.
https://www.garfieldtech.com/blog/on-the-use-of-enums#open-type<= br>
I'd also expect the built-in list of codes to keep growing over = time as more wrappers and edge cases are covered; which is another hint the= domain may not be fixed.

Would a set of integer constants (possibly= grouped in a class or interface) be appropriate? It would be more honest a= bout the open-ended nature of the value space while still allowing meaningf= ul comparisons, without creating false expectations of exhaustiveness.
<= br>

I changed it to the S= treamError class constants and also move the is*Error functions there.
=C2=A0
4. Using stream_context_set_defau= lt to change error_mode looks hazardous

The RFC includes an example = where stream_context_set_default is used to set error_mode to StreamErrorMo= de::Exception globally. I'm worried about the ecosystem impact here: if= any library or application bootstrap does use this,=C2=A0then existing pac= kages using the common @file_get_contents('maybe_existing_file') id= iom could e.g. suddenly throw uncaught exceptions, breaking behavior their = authors had deliberately chosen. This feels like a significant compatibilit= y hazard for code that doesn't control its full execution environment.<= br>
Would it be worth restricting error_mode (and possibly the other new= options) so that they can only be set via per-call contexts, not via strea= m_context_set_default?


I added that restriction and also added context to some stream functi= ons so it can be set explicitly. There will be more function extended in th= e future if this passes.=C2=A0

Hope it's ok no= w! If there's anything else, please let me know.

Cheers

Jakub
--000000000000dd0068064bd5a72f--