Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130212 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 DC3BA1A00BC for ; Sun, 1 Mar 2026 15:09:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1772377781; bh=dv6nUacj8P7HrXmGaXPJRDG591y/qrgR1F+pDApjoAQ=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=OYTk4aw9pMRkcPqCJWeN8POl500v/EXk1N3tAhE4NhD46tvsxz1sEW3x9w55Bd0XU gmD04Kn/yHZH3jdcWW9RbXbcmFsSpIEx6uXPbPZa7GRCH02LaWuFUtDcAHmm6nGIQL Xyk7Y2TYlLBeTEiggXviO9SRjjxTWBFFma98x1yKweUZdfauhzKegb3HiOZJFc4yFI yKHyZna/vSncIB3j3Ji915s4jwCfOeKCHhIyF4vRxGp4i29wvvIISMVd9VTRcBdCr7 wN8ThEtBz8I3FAScuRWMD+TQLsmjByex1ir8Mf+B3lzl4yZfLngNPETi7FUCInzy29 N4fTY2aHVv0QQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id A79FE180042 for ; Sun, 1 Mar 2026 15:09:40 +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=0.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,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-f50.google.com (mail-oo1-f50.google.com [209.85.161.50]) (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 ; Sun, 1 Mar 2026 15:09:35 +0000 (UTC) Received: by mail-oo1-f50.google.com with SMTP id 006d021491bc7-662fe3ff6f6so2557624eaf.0 for ; Sun, 01 Mar 2026 07:09:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1772377769; cv=none; d=google.com; s=arc-20240605; b=b1AmgeVEPZAG9VlBZ5bZfARI45o6aWY/n5uaDTWAqhCtbIjS6SXULZUGJTlQ1A9w4A 5C0qFGydt/kEd3wZdXLXA26Q6+sxR4kLGaUni0jP8wBGICyWcppU8ii2Afs2DBJsyj+j RDth/ZuuE+4GBp08PUMutg9U7whPbLXe8owlfyAfkFSXci/KznJd6PbWyXHe+p6PU1K2 gqWi1ZXf7rAHC0v+yvS1znhQ5jnE4MbyC/IXbWZTLIeTqwDyGP9kNJUlFJUdD6mdrzrw rDphlt3kYqPTHvHdpRwcKIenRZ/Tho0D8CwkBPlQrB5WgBYR7lC9TBU/v3CojahZhoJg a8nA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=jSQz8zHYujhPJamLVO9YvN4qQDWwF9aWCU124hwWGiI=; fh=e1jcWte0mPTSZlyXl/HLkSXX/3nWNC/faQfpUh1NqBQ=; b=WvlIk+e5zdren4+BFvv/ht8vZSYzapzkRv3G4SzATL4DwrLf06CxcpTRyQZanvT9VD lJbo0qMptxpQlXIHIKlB9TOFWz3PxM2cdRJ+zt50MfQRfis1wynyW2dQv5ey2IlEauvm mhqJjmqfI4bRZDD63eybJJv/QvnuZtCgU+TsHfs68BjnDgTQonp1evvZbsk41B73biLO IY5d9WUwI3Od1a2/ViTHGR1ScDtL/MVLDWxzpvwmPmD0/I8QZvsKXmTZvYEyr3tzAL/q an22xK94doWRCezfIDzwXmvOZ6E6S9mddv67DYdeR1joXwdprgKl/1+3lfugJ1/UMrkr 1HTg==; 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=1772377769; x=1772982569; darn=lists.php.net; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=jSQz8zHYujhPJamLVO9YvN4qQDWwF9aWCU124hwWGiI=; b=NWwM6uiNHKNlRPCY1ahiOYCMDeMf+aJUOYBissaZMpcunuu2NzNWz5siDuaXp8xKBO ogDz/EYUM6s7KtJvfl3bUgdDAqPMVSdUv4eVdc0pjbzBNy8UxwkuCpRWUkYJoeIv5okl LcU9/rWjQNFVL45WJ1DIfwvLfl3eCKNAWcxO3UDBWmFRb3Xv6BBT0TmLKL3AWYRBwAWN oRWa5DqbMC0N6oEU311QCWFZdijv4NkcFHEBewRfw42EaO+8eacPmCPaZVHUvyJ56+5o vD9PGDCnvZUhol4W5AEWaCK+n7oRiwlE1U+3esl17ELEW5ipTyvzoAFL3d1a0AbuCkES rhTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772377769; x=1772982569; h=content-transfer-encoding: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=jSQz8zHYujhPJamLVO9YvN4qQDWwF9aWCU124hwWGiI=; b=nBybsvI63wZsA6MsQMysR5vAZwtL9lNxvOo3zkdTZvm/0VtjbQJeC1nwCqznzrrKeM CeX0o5ISdQmzRULyAvGPCA6rbrsTCR/SBgXKitxMvF2N7eqMlgzQ8JrHD+3ZqsM0yztP SfwJdCbtHSyyWH5qMjyiOU5ryNH/sZuLWlU2thwR37/+W0VDu9G2Akxnuzctsv4gDF2W 7HDHeubIemC0PcZNIG5THQV7be4rqW1vfttbJw5keC3IyJSDxUSjAAUW86KnyBI++v// A3As7Hw/ZWoApAq3Wjj82VlzZF+M6+oVAiIgBK6rDGux7cEQtmcY6WeB7WQ+0HYGoxVP gQAA== X-Gm-Message-State: AOJu0YyY+Sgo5jaIb2fx2hXIVza6yp8Kk/qWzAWOfezYIBWf6VTn2ygp f+EqTPj10hFF8TWCQAW9D8ztN4jJavz1WAoYJ9VcYGS9XFJBZJSw4oD/y/iFn0waBMYcfT2vKJO jZTP3+G8zcQ5OITcVVYxxSUUqIecjV5hrDqYy X-Gm-Gg: ATEYQzysDDqvyrbmzdsg+qzaT5Chbk4VfEug/LE5EaHa/Ov7Lv0Q5X4i2NZInigQ86x 19yH1/vDLVeprSflZVz1JHGa0ckXWvcfX2a7+mYRgZ8IrGGzn3nTFsEWkv+iUy9XuwNojGRkssN jzev9GU64l9l+OKQKItR6C3rNevGmRLhHJyac+zUIqDHrrCNa4D0LDjvYsmsHKIdW5P229XIxv4 El3KlImxI+uOTZkhb/bAPKRWU7MuEMm3867mZuLNctgSrudKWCClnnTUS6wdFrFB12OKYpxie7H Wmg2AZlPXMyXCDQOPA0HUekwIGo4gdJ0pkf32ICzCQ== X-Received: by 2002:a05:6820:4cc9:b0:663:9b9:9295 with SMTP id 006d021491bc7-679faf3ddf1mr5777455eaf.57.1772377769513; Sun, 01 Mar 2026 07:09:29 -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: Sun, 1 Mar 2026 22:09:18 +0700 X-Gm-Features: AaiRm53nEyI_tFWY0z1kN9y_mlka-ENTv4YW5DBIKiN4u6wZRhfCXObC4REz2zM Message-ID: Subject: Re: [PHP-DEV] [RFC] Stream Error Handling Improvements To: Jakub Zelenka Cc: PHP internals list Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable From: pierre.php@gmail.com (Pierre Joye) Hi Jakub, On Tue, Dec 23, 2025 at 6:10=E2=80=AFAM Jakub Zelenka wrote= : > > Hello, > > 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 Thank you for this RFC! . It is clearly needed and the error chaining design is great. There are a few points I'd like to raise, the last two being slightly off topic specifically to that rfc but however very related to. So a slightly long reply. 1. New exceptions The current design has a single flat StreamException. This means the exception path requires inspecting the error object to branch on category: catch (StreamException $e) { if ($e->getError()->isNetworkError()) { // retry } elseif ($e->getError()->code =3D=3D=3D StreamError::CODE_NOT_FOUND) { // fallback } } The current design introduces StreamException, which is good. But as a single flat class it doesn't actually allow to use exceptions the way exceptions are meant to be used. One still has to inspect the error object inside the catch block to know what happened. It introduces the syntax of exception handling without the benefit of it. Since the error categories are already well-defined and stable in this RFC, StreamException could be a base class with typed subclasses mirroring those categories: StreamException =E2=94=9C StreamIoException =E2=94=9C StreamFileSystemException =E2=94=9C StreamNetworkException =E2=94=9C StreamWrapperException =E2=94=94 ... This allows the more natural and idiomatic: catch (StreamNetworkException $e) { // retry =E2=80=94 type alone tells you what happened } catch (StreamNotFoundException $e) { // fallback } catch (StreamException $e) { // generic } The StreamError value object can stay as in the RFC (and keep "BC" for the error const's bag), it's appropriate for the inspection/silent mode use case. I see the typed exception hierarchy and the flat value object serve different purposes and complement each other: $e->getError() still gives you full detail when you need it. These are separable concerns currently merged into one class. Since StreamException doesn't exist in any current PHP version, there is no existing userland code catching it. This is a clean state. Adding a typed hierarchy now costs nothing in BC terms, and retrofitting it later would be a BC break. It is more than just syntactic sugar, it allows very clean logic. static analysis tools can reason about which exceptions a function throws, IDEs can suggest catch blocks, and retry wrappers can target network errors specifically without accidentally swallowing filesystem errors. The cost of adding the hierarchy now is low; retrofitting it later is a BC break. 2. Custom stream wrapper and errors How does custom wrappers, be in ext/, or out of core wrappers, exts or user land, can emit errors? Or is it out of the scope of this RFC? For wrappers authors, f.e. in zip, php_error_docref(NULL, E_WARNING, "Zip stream error: %s", zip_error_strerror(err));, or php_stream_wrapper_log_error() it is the classic php error. Both were acceptable and the only way available, without relying on custom methods, but if the stream's error handling is being improved, or made future proof (when possible), together with the typed exception, we could get something good. The typed exceptions give callers a clean API. Adding an emit function gives wrapper authors a clean API. They close the loop. Either one without the other leaves the whole thing incomplete. If typed exceptions exist and stream_emit_error in userland and php_stream_emit_error internally exist, wrappers can emit errors that integrate cleanly with the catch hierarchy, and have better error reporting. Some of the future scopes seem foundational to stream error handling improvements, and risky to delay rather than allowing them now. the slightly off topic ones: Is there a published overall design document for the stream evolution project? The foundation blog post outlines four pillars at a (very) high level, but the relationship between the RFCs, their sequencing/order rationale to be added already, and the intended end state of the streams API are not spelled out anywhere I can find. Having that available would make it much easier to give a more informed feedback on each RFC as it arrives, and to flag conflicts or gaps early. Streams were introduced over two decades ago (afair it was in the early 2000s, by Wez. we aren't younger :), and much has changed since. Async runtimes (swoole, reactphp, FrankenPhp to some extent, etc), fibers, modern TLS, io_uring, and very different application patterns. The error RFC itself acknowledges the BC constraints that shape its design. My concern is that modernizing streams incrementally in 8.x, under those constraints, risks producing something that is improved but still not fit for where PHP needs to go, or ideally should go, particularly around async I/O, where error handling, stream selection, and the overall API surface will need to work together in a coherent manner. Is there a published async I/O architecture that these RFCs are building toward? The other stream related RFCs or the phpf's blog post mention future work about async IO, and related stream topics, which suggests the async design exists internally but hasn't been shared publicly. If that's the case, it would be fantastic to share it (even as a draft design doc), so it can be assessed whether the current incremental steps are pointing in the right direction, or whether some decisions being made now will need to be undone later (or will be impossible to undo without breaking BC). Especially if authors of Swoole (made io uring into their php 8.5 version it seems :), reactphp, etc would surely provide extremely good feedback too. Best, --=20 Pierre @pierrejoye