Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130173 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 BF56E1A00BC for ; Thu, 26 Feb 2026 06:56:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1772089000; bh=olayCPM3dUI0fo+hVMEj456LpaXcfinS3IftH7fvImM=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=NiDdSBhPjh3zbodbCXqw5nvgbxgUm9GUTTe3lyvxGTIB7+8q9atdmTq7IW9YXlxYA dJC3Wofr+XeFfIlD3/S118buWNlyk18AGcdouyhCxob/osZMP+3LUdJw4k/jVHdVAp JcE5n9DIZO/aR6KmeAgZJxgZcG2ud9uzRHYDFcGku+7rrMsr+rYKZtVacTv8eHXBI3 o7soyDJO8R2F1EiIgPeSv3SeGI6tL3++4vf604NIk9VtOQknjKtV9d5QGEuzptw1GT EnUNYs1LuK8e48TNbE2RTqJbSVm4WH7eNnMsKMV94jEwQSsCeQG6BftddF14THiO8+ HjIes2vmWrZog== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 1A7A318004F for ; Thu, 26 Feb 2026 06:56:39 +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.6 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_50, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS, FREEMAIL_FROM,FREEMAIL_REPLY,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-qv1-f45.google.com (mail-qv1-f45.google.com [209.85.219.45]) (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 ; Thu, 26 Feb 2026 06:56:38 +0000 (UTC) Received: by mail-qv1-f45.google.com with SMTP id 6a1803df08f44-899a9f445cbso7459316d6.0 for ; Wed, 25 Feb 2026 22:56:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1772088993; cv=none; d=google.com; s=arc-20240605; b=iv+ehfHwretebUrsAmaXWkmZAH5cQzg1EHLAJzGWt6e9bWJ/nVeGuL/Lf7x2wavP1W /P6p5+MMMI771++rjOhksm9VK3Zvw+KIRhJV0aCL715OqEBXVmQSBNifYLhjePmfO2ci G/wWgwvS+hGRnhzknUq5VS/rvjGtg5MeKGbXke7BVMb3N0hCr7eCHu5kh5F68RPAnDMn 55d6hvMglr2SgfW7/G4QZU5dgrk2wdMdeZbt3Rf453ClcPmegyAJaVKSKXCelTcO+vS5 dO00BizTA7LqXMbtVDUU/Tz/UUivcH8rytfhMnZokHi2VckmISmn72GDKe9yUwdBzuoj /lJQ== 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:dkim-signature; bh=olayCPM3dUI0fo+hVMEj456LpaXcfinS3IftH7fvImM=; fh=e1jcWte0mPTSZlyXl/HLkSXX/3nWNC/faQfpUh1NqBQ=; b=JX8VHzzbp4QcRpg10xyFZ4wLQpnAeGJ90Qp/ezZyjl89CWR9ebMxBrun+Ua9VOccYU gB6dj+iXWCmb70jLR/CHtydMN79DSEBuZPlP4xkor2Z2kFmv7yxExRJpa2lPxTeLZxr6 xtyGt5gFLEn8PaFWLr4Wmkyyifbfb3vVQgU3mfP8G8jvbO9/wLacyY5z4h3s2P3ovXqy EDFElkxK5d2G1/xfq4436Gn8+mwj5+FIkuEiiXh2scBHBV3dlCZMwWlnFqypPnmF3o/i 7sDmHId6MBLBTofMR77TpmbWkB98r6Tgd2fN70w+4v5enhG2t5PlTacTWqM4qd/F4iu+ s2lg==; darn=lists.php.net ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772088993; x=1772693793; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=olayCPM3dUI0fo+hVMEj456LpaXcfinS3IftH7fvImM=; b=ANJZNfYjKmN8qgOSP7545kG6vGkfMFy+878CkmzYNQ0Xy5xIITtNAtUzDvSyb2iq66 DO80dzLsjFHsEyQCIiEHQB4yOMOV35uL5v5DfrkpBKuUxEN6knwAwym0Qpetsl0xVrcP /dL6VJGRE6MBh4cp9JxFkZheycSYpCaR7vWk0gOhhYEPRTX+SVl1vXIC7HmPFQ9zS4C0 8jm7rOqnU1pV3bNV0rrHm72V3nRmOGZfZc/brJxHeIJ44Vvgh6E21HXX4mneIds741BY zYzWDNJQC+EQfC/uVjZI6JmehQlINMzS3772mZI0VOAs8RuPpljq7n49Mk4RB1JhPsoC toLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772088993; x=1772693793; 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=olayCPM3dUI0fo+hVMEj456LpaXcfinS3IftH7fvImM=; b=enmyahB4g1u6b5Wbio/CNxFKLWL7OI9Pt0ZNaVFFGQHHwuzROIie79yocL47dKPxaJ VkbZ3AVFww51G6X2/6NVNQ9H8Y3krtsCGl9mo7T93sbc7Wrp/aibWQOXGWS3wpHUSKwt Hgu7ROpnX/XmXvDL6LE5B229ZEGcQmeP+MYXXnmVn852z4ZcQazmE327QL5kCGnjlEQB a4iUd1Wo9sDkYqAhnRk/Bmj4wHMsVpwqE0TQ13yFuNuVMGcI44rVyD2P03vQojkf02I4 VWTABLBVjUWKRlPvsOKq09/U9SEsBLzKMNIp2g/dx0/bap23g3abSFAwTtJku1za7W+s doZw== X-Gm-Message-State: AOJu0YxB08fzB/FROkun+juZB1dj0GycHyS0rwwisHB8DR7f0MTHARNl Stu1VxXbjKSVoS51kAhbdx+Ui2qDXW7loUC5ompqsQAQfOqZnZ6Tl7KrvD+IZ1IqS2qVsdEN65m WZC8LzJrojhbCWs+JbXFvu2kWvZLj0XxYdvhypx4= X-Gm-Gg: ATEYQzzwq0pvUF23LXjjO6Q06W+hnGwOG624yTFTPbQrm6SJn392qGFnfQXljGbfbqQ aEMFUTJ4+Vny+P9A5GjBr4khoGxipXDKSErlwvBfobWOHHfUOAzLKpEkZHqsQPdNvHng++mVy6I /QRrM6DK8agr+awWC12pyF8T7CeC/R2QQwlM//R8b73qtwmlF3kImkPhw5bxgmFF9EFMiz3kc3l mrKKn2dcj+4FH9owijgOuEOHENcodqxE0t648oCKN+qn4wP2OldMU9I37anJwGzIw035RZ7uAoQ KAaLxYQc+VZLiIInAljP/OZZj4CEMPekXrP+OGoHV1r9xbucD1cgiWyyc17io3xtyHTB+g== X-Received: by 2002:a05:6214:1bc5:b0:897:190:c272 with SMTP id 6a1803df08f44-89979d9b4a8mr283698916d6.62.1772088992849; Wed, 25 Feb 2026 22:56:32 -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: Thu, 26 Feb 2026 07:56:21 +0100 X-Gm-Features: AaiRm51FWgUFh0eK_32JVcny01p8c7lopYu1mdaNWoI7FrbaBsZQiriOKfgIkUM Message-ID: Subject: Re: [PHP-DEV] Re: [RFC] Stream Error Handling Improvements To: Jakub Zelenka Cc: PHP internals list Content-Type: multipart/alternative; boundary="000000000000ede0f7064bb49e0b" From: nicolas.grekas+php@gmail.com (Nicolas Grekas) --000000000000ede0f7064bb49e0b Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Le mer. 25 f=C3=A9vr. 2026 =C3=A0 20:16, Jakub Zelenka a = =C3=A9crit : > 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 stream error handling RFC that is part o= f >>>> my stream evolution work (PHP Foundation project funded by Sovereign T= ech >>>> Fund) : >>>> >>>> https://wiki.php.net/rfc/stream_errors >>>> >>>> >>> 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. >>> >> >> 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|n= ull >> 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? >> > > Yeah this wouldn't make sense as enum but it would probs still make sense > to keep it if it changes to constant > > >> 2. StreamError::$next =E2=80=94 is the naming intentional? >> >> Since stream_get_last_error() returns the most recent error and the chai= n >> travels backwards through time, $next seems to point to the previous err= or >> chronologically. Would something like $previous (echoing >> Throwable::getPrevious()) work better, or is the current naming delibera= te? >> >> > I will double check it but getPrevious() might make more sense. > > >> 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." I= f >> extensions can define custom error codes at runtime, the set of possible >> values would depend on which extensions are installed, and the type woul= d >> 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 doma= in >> 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. >> > > Ok if enum should be closed, then I agree that this should be changed > because there might be new errors. Larry suggested it before but I didn't > see any mention that enum should stay unchanged in future versions. I wil= l > change it to StreamError class constants and add static helper > classification 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 = use >> this, then existing packages using the common >> @file_get_contents('maybe_existing_file') idiom could e.g. suddenly thro= w >> 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? >> >> > Hmm that's how stream context works and it would seem quite hacky to add > restriction on global context (we would basically need to add some > validation when global context is set). What's worse is that it would > prevent to change error handling for cases where it is not possible to se= t > context (fsockopen and various other cases). This is actually in some way > already possible by throwing from the stream notifications (limited to ht= tp > wrapper though) but I can see how it could have bigger impact here. I'm > afraid the libraries will have to deal with that which should eventually > lead to a better code. > Thanks for acknowledging the first items, I'm looking forward to the update. About this last one, I need to insist: that global behavior is going to be a nightmare. Everytime someone proposes to add a new ini setting to configure some global behavior, we say so. The reasons are exactly the same. Existing code will just have to be rewritten, which might lead to better code but also to high friction. Exactly like a BC break - it'll be one actually. About adding validation to stream_context_set_default, that looks like a non issue to me. About fsockopen et al, that's a very good reason to add a context argument. Without that, properly using those function would mean changing the global stat all the time. Better not plan for this. Cheers, Nicolas --000000000000ede0f7064bb49e0b Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


Le=C2=A0mer. 25= f=C3=A9vr. 2026 =C3=A0=C2=A020:16, Jakub Zelenka <bukka@php.net> a =C3=A9crit=C2=A0:
Hi,

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

I w= ould like to introduce a new stream error handling RFC that is part of my s= tream evolution work (PHP Foundation project funded by Sovereign Tech Fund)= :

https://wiki.php.net/rfc/stream_errors


As there has not been much discussion and keep= ing 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 r= equired ofc.

Thanks for t= he reminder! I discussed this with others and we raised the following point= s:

1. StreamErrorCode::None: do we need it?
Having an enum case representing "no error" feels a bit off to m= e. If an API needs to express the absence of an error, would,'t StreamE= rrorCode|null be more idiomatic? StreamErrorCode::None seems like a nullabl= e value disguised as an enum case, and it means callers always have to guar= d against it, which somewhat defeats the purpose of using an enum. Am I mis= sing a use case where ::None is genuinely needed?

Yeah this wouldn't make sense as enum but = it would probs still make sense to keep it if it changes to constant
<= div>

2. StreamError::$next =E2=80=94 i= s 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 error chronologically. Would something like $prev= ious (echoing Throwable::getPrevious()) work better, or is the current nami= ng deliberate?


I = will double check it but getPrevious() might make more sense.
=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.
<= /div>

Ok if enum should be clos= ed, then I agree that this should be changed because there might be new err= ors. Larry suggested it before but I didn't see any mention that enum s= hould stay unchanged in future versions. I will change it to StreamError cl= ass constants and add static helper classification functions there.
=C2=A0

4. Using stream_context_set_default= to change error_mode looks hazardous

The RFC includes an example wh= ere stream_context_set_default is used to set error_mode to StreamErrorMode= ::Exception globally. I'm worried about the ecosystem impact here: if a= ny library or application bootstrap does use this,=C2=A0then existing packa= ges using the common @file_get_contents('maybe_existing_file') idio= m could e.g. suddenly throw uncaught exceptions, breaking behavior their au= thors 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 o= ptions) so that they can only be set via per-call contexts, not via stream_= context_set_default?


Hm= m that's how stream context works and it would seem quite hacky to add = restriction on global context (we would basically need to add some validati= on when global context is set). What's worse is that it would prevent t= o change error handling for cases where it is not possible to set context (= fsockopen and various other cases). This is actually in some way already po= ssible by throwing from the stream notifications (limited to http wrapper t= hough) but I can see how it could have bigger impact here. I'm afraid t= he libraries will have to deal with that which should eventually lead to a = better code.=C2=A0


Thanks for acknowledging=C2=A0the first items, I'm looking for= ward to the update.=C2=A0

About this last one, I n= eed to insist: that global behavior is going to be a nightmare. Everytime s= omeone proposes to add a new ini setting to configure some global behavior,= we say so. The reasons are exactly the same. Existing code will just have = to be rewritten, which might lead to better code but also to high friction.= Exactly like a BC break - it'll be one actually.

<= div>About adding validation to stream_context_set_default, that looks like = a non issue to me.
About fsockopen et al, that's a very good = reason to add a context argument. Without that, properly using those functi= on would mean changing the global stat all the time. Better not plan for th= is.

Cheers,
Nicolas

= --000000000000ede0f7064bb49e0b--