Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130203 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 1D7CF1A00BC for ; Fri, 27 Feb 2026 22:35:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1772231708; bh=OAF6jv7dAGT9UA1rBdU8tTaMAPfrAlIgagLtys9GSa8=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=Qd+B7m4+135Mm75+ZUaQ9C2/8kBBPNAz+LO144ZutAdsyLejIebODwPzP0MNVnKiX mmSWYgHWzCuOdJyYdDxrUhSaAeApbBiWPEJxQ51BV8/i25bmopf+u43oimNpJJQQUN OMnxSR0r6wTK051lyb9IUioy2h5LlTdPdkMOWamgxXgsb4CD/zDaAeIVrsm8h3DnVx g5Bby5A48jgLg4Jxe59BrvMdPENaLStOWIzXl101rNc8QFddq9GsY/ROvEUrJhUgIu upP8lceaNrbUPWWkqu4D7sX3WTUtXm4Y6/+dv5RpOJONePZcJi/fi94p7vEFv1o1bL YyCpXuQfPw/kQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id B12BA1801DA for ; Fri, 27 Feb 2026 22:35:07 +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_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-qt1-f180.google.com (mail-qt1-f180.google.com [209.85.160.180]) (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:34:57 +0000 (UTC) Received: by mail-qt1-f180.google.com with SMTP id d75a77b69052e-50334dd44d2so28881521cf.1 for ; Fri, 27 Feb 2026 14:34:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1772231691; cv=none; d=google.com; s=arc-20240605; b=jC/sPaEdR1rCbyC5a3K5RcXD5ERylBfblYd3ouZ3+j+8ndxlBxwgU9j3AcZwfTo+j7 DluxWNDBXPYmPiecrR/kiQLORxG3YLmA9gCcKY7AEasdVxbZ0NzIKqcgG6LSEbWEdDIV WYdHGmfa2MYvHhp/wmnkJMX8taAqXqvbOZU/fdczhl8J08ObULqoPidGaIs5/iWI41kP swSPQx0t9mEV0WeJAOSHR/PmDdx8EIBBzWNhTHQS8e9yHmDBai7n74P4VC/Q+OBwiukW t0UQEo4rld1JEDdPfoIfqW1ki3GKDrEtjvjOVW8f4nMr4C5AXuMYkQO1N+A2fETjhQv3 laMQ== 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=OAF6jv7dAGT9UA1rBdU8tTaMAPfrAlIgagLtys9GSa8=; fh=e1jcWte0mPTSZlyXl/HLkSXX/3nWNC/faQfpUh1NqBQ=; b=FHw+N23y6rEmBUgtJHdp0l56rR2ukuWqQqtv4HZCCSjGrL+fugswcifhMIhNLOS1yB LzdUbxiWUN28LnK2SDA3QbY9YkWS07rVQrDcqFn6noWUypwkx3pZnNlyHTIsFcAQHwM4 6tUozvJWRi66OOBI5g0WbVE0LlpH/kU7/AHLob8woG/HcIsQdQTeyiGeXbvzI+F2ezPg YM8K0fnkEWgjNxwiM/8amY9ySGJnc0gsjus9HbxDg77TfBRc7VjyCg7/RcpVOcNSBMXw 3Pd0ds1jKrFolc4JwqV8e6l/MWtKgaMix9+SYVgAXuyf/22DjCh1UJsyMskBEqpiDb5y rnbw==; 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=1772231691; x=1772836491; 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=OAF6jv7dAGT9UA1rBdU8tTaMAPfrAlIgagLtys9GSa8=; b=Ac+AbQ6oi0eYbZlssftjBVp5+f3ZUQgYZIMsiu8DY5sAHnviZmmkppHm5UxiHTmavm 5svLeUo1rBOqDVZk+d1KrQICKNqRZbq2ZjWDHSj77fBBaI4/sRnpcF8kuhpAX52hSa8k C/7IA6SmfnZLsDqrf3+zG+xQHF1ysMruJ2MzXfBXo9B2nbL3cyNy5sicF73FXClRet+V qsp0UZPDSukFLv+I/9ht2ufv/Z6dKhDZBbUnYVdHKw105op85cEIBmLqp+wVMJcm6ZzF NHoZl+sXpuIZ60t8YrM/gidlH5Zz3rO8LtB1lNOni5GRFILDIycLrbsHR1qCJLSkvupc Hp3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772231691; x=1772836491; 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=OAF6jv7dAGT9UA1rBdU8tTaMAPfrAlIgagLtys9GSa8=; b=M8gdo3FAqVqd1Sdma9WPTtQCOFVhAITP+Cr4955hno0lQB+/q29rFL3NWKf2Zczvkb I3pj5rpr6oH8Ces1VZYv63VN0WPIOhB2T/k/f4Tsa1NmlpvSb/aS0buHpwdgJGIfz+80 jQrMvtlksO8zSO5eBvOvZ7kP4a8DWtur6zJiYKcdGJwmPrbBsvVDxcZ1jicreEnGqFUa o4VBgtB4fNG/6LlNNAasPhHX+bVoQX2avfM/0a4V6VDl2/o+NlxdTM+0yjqlUWakoUbR LFcEbrX1o7lT4speytt7oaGBm66FbQ0apDlzU2XwtBd49W0PmGk5eA91aTp18826qsMk 5Hcg== X-Gm-Message-State: AOJu0YxQKRJ2vO+GVcRTW5eYwcdGQeQa0yZ190+gYOjnmFQBgrav0H/o 3CNYGN4LGB8AI4FmisdDnMrsNlU+Qc2VCbKG/oGIdHuTd1EYPn5hgeOJSCukZD1RwRitF/LAZB0 WfwSpEUWXrgypew5AitADHlZ7dzYMyxQ= X-Gm-Gg: ATEYQzzsY8IBP/KN6sM6iii9+Ewf1kY14E7iMXgDrKfegauJ8JBdmbNjNLCTOop2Hil 8gWihuuUU4lzU/ruWLQYP4fs9R8DGEv/IFpohmQAgQD7E0gCedie3PTr5hvYZwd4kUGR3/Wd8ig 7/LUrLBw/Cck7Hn5Ne2RkPZNBBjWOzvQtGZ5wPidPb0jj5DbvRgBbfRNOZok/6qoQNynqJmjh/i vAxcyGLHrGHi8xnJhUKuVQuhLDAIQT3s//WpO67Vw1HZFCnenEm31HbglEhHZUWHPYpejzeCJ3P ETYzkYLkthR/rVI8hH5/0Hkisf5ZzVH0u1wQp1byi3VYqJ3ghlZynbquQ2dhp42NEVZEcouYMgJ E8SryqSAPFjkyS1MPWxeQy1+a+wekOm6mGQ== X-Received: by 2002:a05:622a:14cb:b0:501:4164:8c2a with SMTP id d75a77b69052e-50752916248mr62137391cf.67.1772231691366; Fri, 27 Feb 2026 14:34:51 -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 22:34:40 +0000 X-Gm-Features: AaiRm50fii8N-ecuW4ejU4oWvJUC71z0ntljadvWC1tYdKxl2YBUNJCV5TSxHgI Message-ID: Subject: Re: [PHP-DEV] Re: [RFC] Stream Error Handling Improvements To: Jakub Zelenka Cc: PHP internals list Content-Type: multipart/alternative; boundary="0000000000006c7504064bd5d895" From: nicolas.grekas+php@gmail.com (Nicolas Grekas) --0000000000006c7504064bd5d895 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Le ven. 27 f=C3=A9vr. 2026, 22:21, Jakub Zelenka a =C3=A9cr= it : > 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 >>>> >>>> >>> > 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 i= s >>> 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|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? >> > > > As I removed the enum this is no longer issue. I kept none as constant fo= r > 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 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 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 mos= t > of the time not that useful but might add a bit more context so that's wh= y > 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." 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. >> >> > I changed it to the StreamError class constants and also move the is*Erro= r > 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? >> >> > 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. > Looks nice thanks! I'd just explicitly tell what happens when one tries to change the error mode globally. An exception? Which one? Cheers, Nicolas > --0000000000006c7504064bd5d895 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


Le ven. 27 f=C3=A9vr. 20= 26, 22:21, Jakub Zelenka <bukka@php.net= > a =C3=A9crit=C2=A0:
Hi,

On Wed, Feb 25, 2026 at 7:11=E2=80=AFPM Nicolas Grekas &= lt;nicolas.grekas+php@gmail.com> 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 Tech Fund) :

https://wiki.php.net/rfc/stream_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 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.


The update means that the vote will not happen = in the next two weeks...
=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" f= eels a bit off to me. If an API needs to express the absence of an error, w= ould,'t StreamErrorCode|null be more idiomatic? StreamErrorCode::None s= eems 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 usin= g 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.
=C2=A0

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

Since stream_= get_last_error() returns the most recent error and the chain travels backwa= rds through time, $next seems to point to the previous error chronologicall= y. Would something like $previous (echoing Throwable::getPrevious()) work b= etter, or is the current naming deliberate?


I checked this one and realised that $next is ac= tually better because it's better to keep the first error which for str= eams is really the useful one. The follow up errors (if any - most of the t= ime there's just one) are most of the time not that useful but might ad= d a bit more context so that's why they are chained. I added this reaso= ning to the RFC.
=C2=A0
3. Should St= reamErrorCode really be an enum?

The RFC lists in its "Future S= cope" section: "Extension-specific error ranges - Reserved ranges= for extensions to define custom error codes."

This gave us pau= se. Enums in PHP are intentionally a closed, finite type: their value is pr= ecisely that "invalid states become unrepresentable." If extensio= ns can define custom error codes at runtime, the set of possible values wou= ld depend on which extensions are installed, and the type would no longer b= e truly enumerable.
Larry touches on this exact tension in this post: wh= en the value space needs to be open or user-extensible, an enum is the wron= g tool.
https://www.garfiel= dtech.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 domain may not be fixed.<= br>
Would a set of integer constants (possibly grouped in a class or int= erface) be appropriate? It would be more honest about the open-ended nature= of the value space while still allowing meaningful comparisons, without cr= eating false expectations of exhaustiveness.


I changed it to the StreamError class constants= and also move the is*Error functions there.
=C2=A0
4. Using stream_context_set_default to change error_mode lo= oks hazardous

The RFC includes an example where stream_context_set_d= efault is used to set error_mode to StreamErrorMode::Exception globally. I&= #39;m worried about the ecosystem impact here: if any library or applicatio= n bootstrap does use this,=C2=A0then existing packages using the common @fi= le_get_contents('maybe_existing_file') idiom could e.g. suddenly th= row uncaught exceptions, breaking behavior their authors had deliberately c= hosen. This feels like a significant compatibility hazard for code that doe= sn't control its full execution environment.

Would it be worth r= estricting 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 restric= tion and also added context to some stream functions so it can be set expli= citly. There will be more function extended in the future if this passes.= =C2=A0

Hope it's ok now! If there's anythi= ng else, please let me know.

Looks nice thanks!

I'd just explicitly tell what happens = when one tries to change the error mode globally. An exception? Which one?<= /div>

Cheers,

Nicolas=C2=A0
--0000000000006c7504064bd5d895--