Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130172 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 E29C51A00BC for ; Wed, 25 Feb 2026 19:16:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1772046995; bh=KIDTzsdWE5JjM0yFtPmai03YHoH4zoFk4wrJcmFeXl4=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=d9S399N9Wor8lLwVPK4BbutzxtIukVf4j8ezgI5Dt9cgVEOgMvUxWyL7cLRlOAmkc 9Ut4VYNIKN+vC7Wmw9Bus4WB0ob5r2UjLjZPFwcF4ggcg4VVUSxVV0jo6R8wR0bpj5 snu7nuqnT43VcIgnaBK3MOiXoVWSK3JnnyPAec67oaxVGh39347GMyMvXAnkmTu5fc fTL3rndMjF7e7rWRXfoa8Rs0wEPB9Jhld9M1zstX6o6PaKti7dyIThS8YAvVyG6gD0 qdbKuLTyVcYLfg5ugdHNWDXbIk0bcZQMknj0WnxIw86R8NyzM03nOBsGO67x4fsucc GYG8b2SIHVxcQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 6FE6918037E for ; Wed, 25 Feb 2026 19:16:31 +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_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-lj1-f170.google.com (mail-lj1-f170.google.com [209.85.208.170]) (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 ; Wed, 25 Feb 2026 19:16:31 +0000 (UTC) Received: by mail-lj1-f170.google.com with SMTP id 38308e7fff4ca-38706f96202so590421fa.3 for ; Wed, 25 Feb 2026 11:16:25 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1772046984; cv=none; d=google.com; s=arc-20240605; b=TU+SnlS9kODEhYfd8GTXS0I1dHc4A5Awcwu2P//KVDkrWo92tZxBlGx+rCcwoFSKYc 4D9AuI9AXn+Wi6EkzIoJa3LTh6lCOggzzHeg4qI+CJOgcIOk19RFhzMHlyyV7eeRaAhp wyTm35+SzkEPCxOTstXcWaWevpIdernj+ShvjXW9qOk3a+J7Q/JqqwIkdCJPENfFyt4x D8p+Fib4qB3ncw5DgmRLTVZqRUzRJgJBHzzVIUGzvoj1JqPwXdA+QpUpdXKEz5Cm7KS2 yQXVxJhLgWJndDWUVa/Td0aWFrotZo3F4JAalsJq/OdFpArhBcuJElcfQrX+bPYBTIcr wFqA== 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=KIDTzsdWE5JjM0yFtPmai03YHoH4zoFk4wrJcmFeXl4=; fh=+Olut09awgBB5IxEO9xPIU68miEei4hvoITNrzLyq5c=; b=KL63RenPRD2UGksj99pDz6Yjvu+6wOUmfZZpEf9ogPHTHuoKkYXX7LDgnDuLqJRji1 BUn/1mgC8ff8J9rlHDutiFzsMdt0/FZCkrFF39PTGKVbf41vHhMZXVZXAqkQTptLtlHE 11+MLKPDvYYJxt8Gl4BppYVu93aoPkZC3wuxqcZ3D6/YPtr7gSPJud8JxNdXBLL5I/2U BtHsLPaLgI7CiZVuF5tDrK8OpgvdA0WE0pt8aj/PuKodJicx6H1nkPINXBeczQRDFGlL DHR2oMYzYO31ILzCjYF6Nmaf1Hz8lyo8yZD1kfSt3h+k2bTF0/vq1E0TIktvh4z2zhsP Efzg==; 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=1772046984; x=1772651784; 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=KIDTzsdWE5JjM0yFtPmai03YHoH4zoFk4wrJcmFeXl4=; b=GbU2M0dSJWGBTjSpoBR1u/mx+fOZ4lO31E1vmi29d9ASeMOeq5Gm6glxmmAUqB5rSy Xlc9m+m+scwLBrbpB3QvyYVV5h1UCfqZ6dt3nTfObKEZBf6tWa1VwmrV91Gg8Xi75Pm7 +mQTmmOjERtRPu6URSqktODA3boZHaGjFeU/Ff5xo9FuEmIOf4fFx9F8vp6q1AAWP4BV vmT4IB80M8aHOPpnjZqA0YYkW0BKdSQ2pnW58+SdvpGejejxLeCfnfOcDQZimcDcydA1 RATmH/4mFY8hzAv2oDSqDxqfClDtgoeA9Mm9imKDfBgi0Ytp+OnreCIGp5DQd1Sc4hbw gMEw== X-Gm-Message-State: AOJu0YxzPXJQAXjU4jCBag972MFawGO0PYcjFpAvGbmf52iRxGILqRmT zXrQfk/uoU1D1Hk9dzYDki27LSeQ00KCL82eZ1NpjLlfWyqTOX5PXjk41l6ldAMdiizJBOAFljw +dU9fCUFNKqEZQX8GG6xEWyZZheg5b24= X-Gm-Gg: ATEYQzy6gaWuQokbrc3NJ8Zmdb9LR5cfPS19khM9eDW0G0faX28tDL9XUVBEJ37CIu/ E6AJwEBMYGUKwM1Fd4DTTt91Twpt8pBzyUlwVF+t24TnoyVBr+eirs++mEe782iLCKp5/8HGVKS CZSNQNKh2roC/ZpfAAOhNuyje37zx+iGmBKjhDeApliuUFbhG+W8xnQTqXHrD1HiFIDOkG7tjcp JgpMh27JpFDeUfTnhJ/5tp5PqPBz4Lp2re+R7mCE2kARlsxLrSUCNVitlPvxBo1f9AzTyviyVsY j+sNGpq6hezQRYLlZA== X-Received: by 2002:a05:651c:1602:b0:385:beca:f6d2 with SMTP id 38308e7fff4ca-389a5c92b9bmr55205961fa.1.1772046984170; Wed, 25 Feb 2026 11:16:24 -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: Wed, 25 Feb 2026 20:16:12 +0100 X-Gm-Features: AaiRm52OLi7WLnyvJRz-WFka3_XFJRm0PPetf0JUj5VDN6kuNfQ5x5tivhbURUI Message-ID: Subject: Re: [PHP-DEV] Re: [RFC] Stream Error Handling Improvements To: Nicolas Grekas Cc: PHP internals list Content-Type: multipart/alternative; boundary="000000000000045323064baad76a" From: bukka@php.net (Jakub Zelenka) --000000000000045323064baad76a 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 >>> >>> >> 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. >> > > 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? > 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 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 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." 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. > 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 will 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 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? > > 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 set context (fsockopen and various other cases). This is actually in some way already possible by throwing from the stream notifications (limited to http 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. Cheers, Jakub --000000000000045323064baad76a 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


As th= ere has not been much discussion and keeping the patch up to date is a slig= ht 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. Str= eamErrorCode::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|null be more idiomatic? S= treamErrorCode::None seems like a nullable value disguised as an enum case,= and it means callers always have to guard against it, which somewhat defea= ts the purpose of using an enum. Am I missing a use case where ::None is ge= nuinely 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 is the naming intentional?

S= ince stream_get_last_error() returns the most recent error and the chain tr= avels backwards through time, $next seems to point to the previous error ch= ronologically. Would something like $previous (echoing Throwable::getPrevio= us()) work better, or is the current naming deliberate?

=

I will double check it but getPrevio= us() might make more sense.
=C2=A0
3= . Should StreamErrorCode really be an enum?

The RFC lists in its &qu= ot;Future Scope" section: "Extension-specific error ranges - Rese= rved 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 th= is post: when the value space needs to be open or user-extensible, an enum = is the wrong tool.
https://www.garfieldtech.co= m/blog/on-the-use-of-enums#open-type

I'd also expect the bui= lt-in list of codes to keep growing over time as more wrappers and edge cas= es are covered; which is another hint the domain may not be fixed.

W= ould 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 f= alse 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 ver= sions. I will change it to StreamError class constants and add static helpe= r classification functions there.
=C2=A0

4. Using stream_context_set_default to change error_mode looks hazard= ous

The RFC includes an example where stream_context_set_default is = used to set error_mode to StreamErrorMode::Exception globally. I'm worr= ied about the ecosystem impact here: if any library or application bootstra= p does use this,=C2=A0then existing packages using the common @file_get_con= tents('maybe_existing_file') idiom could e.g. suddenly throw uncaug= ht exceptions, breaking behavior their authors had deliberately chosen. Thi= s feels like a significant compatibility hazard for code that doesn't c= ontrol its full execution environment.

Would it be worth restricting= error_mode (and possibly the other new options) so that they can only be s= et via per-call contexts, not via stream_context_set_default?

=

Hmm that's how stream context wo= rks 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). Wh= at's worse is that it would prevent to 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 possible by throwing from the stream= notifications (limited to http wrapper though) but I can see how it could = have bigger impact here. I'm afraid the libraries will have to deal wit= h that which should eventually lead to a better code.=C2=A0

<= /div>
Cheers,

Jakub
--000000000000045323064baad76a--