Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130175 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 183401A00BC for ; Thu, 26 Feb 2026 15:03:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1772118194; bh=3duSwKh71jekF0cxVfunciR0tt5JPUjb2R2NQViGhQc=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=Bf9dTEiW3L5GDJciHI3zf4CsS+cN/7jmzeP44GUU5ymVwWLRbjKQeJIPnKmocwzKU liBEKb25cSpQ83R0Io5QT+WOSdXquiKIDCyuw5/WCZ8iKrkzVUujtLD0azIRmdHnqc t58PUSEfoltlmkt/3JiQqCPwXJOs3642B54LGe5KZA9Idzle0H6HCoq/tJKONqgtEz jx7iNNTWBcJibJMKdqu3tSreX7TjJZnyPz8qzCgAoSdP4PdHwQLz4kyLEw3V5ICFHK Yo6k3xTpFAtjtXWFFECl0/FDFw+8NciZKwI3hBOzv5IqedzBLXYZAg/k4zpya59geB VSYMk5JSs3Sgg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id B232E18003B for ; Thu, 26 Feb 2026 15:03:12 +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-f178.google.com (mail-lj1-f178.google.com [209.85.208.178]) (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 15:03:12 +0000 (UTC) Received: by mail-lj1-f178.google.com with SMTP id 38308e7fff4ca-389f173b91fso8483601fa.1 for ; Thu, 26 Feb 2026 07:03:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1772118186; cv=none; d=google.com; s=arc-20240605; b=P1rAwckbrX9dcjR5ZgiHJWH50PKKFBOr5NQ/Rona3vOFfa1fAm/M8K9+xYcK91mjyN fsUAPoiqM7tvHAxL55QzbrSqjIHF1VGiEYLMezT8+azWao3kR7o3H1PpV3gJvAeFgtMe AZ0ttbhJ9AWcUyDxhxDXWEX9X+SRdC+jHTsjiCqJPFyg6aANDmnRRIvCR7XufysaQWyC gGNV3Tm0iAzVbHtH338/vrCWijMoPouXyLLxb/9iGi7QvhYX+2V4JItNJJ5Nshy7nFrC 8Jz70Elqs7G24WwlqQhACjZiYOWQvaWhuAK2go1lM54SVJl+crwhWSwHG54vX06YX0mf JjVA== 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=3duSwKh71jekF0cxVfunciR0tt5JPUjb2R2NQViGhQc=; fh=+Olut09awgBB5IxEO9xPIU68miEei4hvoITNrzLyq5c=; b=Sla882+T3E61uEWR0v2koIc1sm+4a/YcVpPVN3/o8bPHQGuoBAh6ceCZ82odvLTyhG 5ziAfuIdn59zX6ZgY3YJymxDnUjhXGcyN5NOqn2/KoeQBEvnIzx7z/86q1eUK3qZuDnZ Fb3mAebuCF3PuSWnuZE4VRTQshySxRuGOPQJWUJsDGXdmLo9kWiur86LGw4QLHEOdmjr 9I2pRht4kE1XeEVrDFp4HxmpxJZ7z6FVAqZNV0LAy9VHuIL/DR3t7iWnV21JcuuMOFqj UbhEAS5z/4V6EPxMkDLBqfFKMQU/EVcKCUqL7StomrqiRzPh6GvwMCIdx+uG78t7oJdq jZjw==; 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=1772118186; x=1772722986; 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=3duSwKh71jekF0cxVfunciR0tt5JPUjb2R2NQViGhQc=; b=rCEWbshzhXAcCYpn9PB/wmInjxo9dLYYYc2bvB2TWZEv/ukSh58JNzIvzzI3PBhnER oDxCpobbYUR2IL4ASeAjAAcpt39McVH1o6WmzXKjOUpKs4nz2jZSltbVJyn65PSWWjTS PL6feHAnNG9JXEMizDVMImXsz2DAs6ZlONIRrsYXy2D/wfaHrpAxwEXS/vQXV+UfeFOS YpnWS9iBrJ4CbVJmnfT9UCcMljBhGCzJ8nEsgzmUAUJbPXa/sgevfALLFdSfoL1Dt3bh rkzkIr8I4krGYtpCB1GTrboVWuVgnl9zb+DtoomZrmgLNlVW8t+WhRLw4j+0dIqaC881 fyjQ== X-Gm-Message-State: AOJu0YwZn/nsL1m5SC/LI/tLC6Bx4kuzh/hyc4lfrKF/PstKyKEShUGH MH6rZeeAdfrEHweBVwkSos6HeOmHxQ32cxjsK+OHpfmeDHFNKglIG2YZi09cODxQ4Kntg7+9tEI zzF9OF6IJU7u+TTPEmdPDzZsfsOEyx7U= X-Gm-Gg: ATEYQzzpHNVilUT+A67JjNVlBqxAa55DMf2RMqaz1GAHdsZf0+DqurrsbNjSeAf8SDL r4/5mVecJ1tFvt90GyAAcabGlOtbBP8uhFtsb7kX/ryRB2LbwKY2uTdbvJyF5bon5uW1TNVrmr2 z2rxh9npXTWeFCENiPyu1PELkP4qXEhy7dclng1zv1JPJ7IEFtZ2TmGNM2t086WOy5C8f1By0tV A6vXd3m0TLWu8KKfM3pBYpIJFzu0EGXpWibxKBZRnaDYFuJWC6jFxLfsj9E9O31w0V/tP0zz7Ob K+L/k1glfAMo0DWE3Q== X-Received: by 2002:a05:6512:b2a:b0:5a0:ef71:b7a6 with SMTP id 2adb3069b0e04-5a109ab18eamr945598e87.30.1772118185302; Thu, 26 Feb 2026 07:03:05 -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 16:02:54 +0100 X-Gm-Features: AaiRm505wnCXnIehBt0nH75j5cAatMlrxlhvZUyO2X4Qu3fKZhrNjKAVnLM7yoM Message-ID: Subject: Re: [PHP-DEV] Re: [RFC] Stream Error Handling Improvements To: Nicolas Grekas Cc: PHP internals list Content-Type: multipart/alternative; boundary="000000000000ef60d2064bbb6ac0" From: bukka@php.net (Jakub Zelenka) --000000000000ef60d2064bbb6ac0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi, On Thu, Feb 26, 2026 at 7:56=E2=80=AFAM Nicolas Grekas wrote: > > > 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 >>>>> of my stream evolution work (PHP Foundation project funded by Soverei= gn >>>>> Tech 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 o= r >>>> 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 a= n >>> API needs to express the absence of an error, would,'t StreamErrorCode|= null >>> 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 sens= e >> 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 previ= ous >>> error chronologically. Would something like $previous (echoing >>> Throwable::getPrevious()) work better, or is the current naming deliber= ate? >>> >>> >> 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 runtim= e, >>> the set of possible values would depend on which extensions are install= ed, >>> 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 dom= ain >>> 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 wi= ll >> change it to StreamError class constants and add static helper >> classification functions there. >> >> >>> >>> 4. Using stream_context_set_default to change error_mode looks hazardou= s >>> >>> The RFC includes an example where stream_context_set_default is used to >>> set error_mode to StreamErrorMode::Exception globally. I'm worried abou= t >>> 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 thr= ow >>> uncaught exceptions, breaking behavior their authors had deliberately >>> chosen. This feels like a significant compatibility hazard for code tha= t >>> 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 s= et >> context (fsockopen and various other cases). This is actually in some wa= y >> already possible by throwing from the stream notifications (limited to h= ttp >> 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 b= e > 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. > > Ok I think you are right that the BC impact would be just too big so I will add that validation. Kind regards, Jakub --000000000000ef60d2064bbb6ac0 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi,

On Thu, Feb 26, 2026 at 7:56= =E2=80=AFAM Nicolas Grekas <nicolas.grekas+php@gmail.com> wrote:


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

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

=

Thanks for the reminder! I discussed this with others a= nd we raised the following points:

1. StreamErrorC= ode::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 o= f an error, would,'t StreamErrorCode|null be more idiomatic? StreamErro= rCode::None seems like a nullable value disguised as an enum case, and it m= eans callers always have to guard against it, which somewhat defeats the pu= rpose of using an enum. Am I missing a use case where ::None is genuinely n= eeded?




Ok if enum should be closed, then I agree that this should be change= d because there might be new errors. Larry suggested it before but I didn&#= 39;t see any mention that enum should stay unchanged in future versions. I = will change it to StreamError class constants and add static helper classif= ication functions there.
=C2=A0

4. Us= ing 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 t= he ecosystem impact here: if any library or application bootstrap does use = this,=C2=A0then existing packages using the common @file_get_contents('= maybe_existing_file') idiom could e.g. suddenly throw uncaught exceptio= ns, breaking behavior their authors had deliberately chosen. This feels lik= e 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 basic= ally need to add some validation when global context is set). What's wo= rse 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 a= ctually in some way already possible by throwing from the stream notificati= ons (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 whic= h should eventually lead to a better code.=C2=A0


Thanks for acknowledging=C2=A0the fi= rst items, I'm looking forward to the update.=C2=A0

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 c= onfigure 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 c= ode but also to high friction. Exactly like a BC break - it'll be one a= ctually.

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 tha= t, properly using those function would mean changing the global stat all th= e time. Better not plan for this.


Ok I think you are right that the BC impact would b= e just too big so I will add that validation.=C2=A0

Kind regards,

Jakub
--000000000000ef60d2064bbb6ac0--