# Deprecation of the Error Control Operator (@ symbol)

- Thread: https://externals.io/message/89939
- Original archive: https://news-web.php.net/php.internals/89939
- Started by Junade Ali on 2015-12-31T14:52:58+00:00
- Messages: 45
- Page 1 of 2: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/89939.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #89939 — Junade Ali — 2015-12-31T14:52:58+00:00

URL: https://externals.io/message/89939#89939

Hi all;

I am looking to submit an RFC in order to remove the error suppression
operator in PHP, namely the @ symbol.

I am happy to implement this, although it is merely a concept so far.

My reasons for looking to do this are:
- the error suppression operator leads to developers being lazy about
wrapping things in issets, try/catch blocks or not handling errors correctly
- this leads to painful debugging for developers working on projects with
high technical debt
- it's slow (though admittedly not that much slower)
- careless error suppression can be reduced by forcing developers to learn
about how to properly handle errors
- when the @ symbol is used to prepend database queries, when there is a
genuine error, it can cause the rest of the script to run successfully
causing data integrity issues. If developers were forced to handle errors
correctly this would be less of an issue.
- lastly, this operator can lead to scripts dying due to a fatal error
without any explanation of why, leading to painful debugging; all because a
developer was too lazy to wrap a variable in an isset.

Aside from doing this, there are a number of alternatives: re-engineering
the behaviour of the error suppression operator and potentially bringing
into the scope of a function (e.g. silence()); this said, I still feel this
would contain similar issues as it wouldn't address the underlying issues
of lazy error suppression.

Lastly, I recognise this will be a big change to PHP; but I feel it is
necessary to enhance the quality of PHP error handling. Let's not forget
that PHP managed to successfully deprecate the MySQL library.

Looking forward to hearing your thoughts.

Thanks

---

## #89941 — Mark Baker — 2015-12-31T15:22:30+00:00

URL: https://externals.io/message/89939#89941 · In reply to: #89939

> I am looking to submit an RFC in order to remove the error suppression
> operator in PHP, namely the @ symbol.
While few and far between, there are still valid use cases for the 
suppression operator, for example when using curl


-- 
Mark Baker

  _________
|.  \     \-3
|_J_/ PHP |
|| |  __  |
|| |m|  |m|

  I LOVE PHP

---

## #89942 — Dennis Birkholz — 2015-12-31T15:41:50+00:00

URL: https://externals.io/message/89939#89942 · In reply to: #89939

Hi all,

Am 31.12.2015 um 15:52 schrieb Junade Ali:
> I am looking to submit an RFC in order to remove the error suppression
> operator in PHP, namely the @ symbol.

before you can deprecate the @ operator, there is a lot of work to do
beforehand. A lot of functions print warnings when they fail (in
addition to returning false). All these warnings have to be removed and
put into the matching error()/errno() functions. Before that there is no
way to remove the @ operator. Otherwise you have to disable error
reporting for warnings and that would be far worse than usage of @
currently is.

Greets
Dennis

---

## #89943 — Patrick ALLAERT — 2015-12-31T15:52:53+00:00

URL: https://externals.io/message/89939#89943 · In reply to: #89942

Le jeu. 31 déc. 2015 à 16:42, Dennis Birkholz <php@dennis.birkholz.biz> a
écrit :

> Hi all,
>
> Am 31.12.2015 um 15:52 schrieb Junade Ali:
> > […]
>
> before you can deprecate the @ operator, there is a lot of work to do
> beforehand. A lot of functions print warnings when they fail (in
> addition to returning false). All these warnings have to be removed and
> put into the matching error()/errno() functions. Before that there is no
> way to remove the @ operator. Otherwise you have to disable error
> reporting for warnings and that would be far worse than usage of @
> currently is.
>
> Greets
> Dennis
>

As Dennis said, there is a huge work to be done before that, not that it
shouldn't prevent you from doing that RFC, but this one should therefor
contains a list of all prerequisites and possibly links to all RFCs yours
would depend on.

Cheers,
Patrick

---

## #89946 — Stanislav Malyshev — 2015-12-31T21:10:02+00:00

URL: https://externals.io/message/89939#89946 · In reply to: #89939

Hi!

> I am looking to submit an RFC in order to remove the error suppression
> operator in PHP, namely the @ symbol.

I don't think it is a good idea, currently, for the following reasons:

1. A lot of functions produce error messages which may not be important
in specific scenario, and the users should retain control over if they
want them or not. Checking does not solve the problem, because a) it's a
lot of unnecessary boilerplate code and b) the fact that you checked
doesn't mean the situation is the same when you use what you checked -
and race conditions are hard to debug.
For some functions, you may not be even able to predict when they may
output error messages - such as ones relaying them from third-party
library. Of course, better way to handle them would be to return error
status and use error reporting function, or have structured exception
handling (or both) but it's not the case for many existing functions.

2. There are scenarios where @ saves a bunch of boilerplate code -
simplest example:

@$counts[$item]++;
vs.
if(!isset($counts[$item])) {
  $counts[$item] = 1;
} else {
  $counts[$item]++;
}

Now imagine you have to write 20 of those - which is easier to write
*and* read? Of course, one could argue the notice maybe should not be
produced - but it is.

> Aside from doing this, there are a number of alternatives: re-engineering
> the behaviour of the error suppression operator and potentially bringing
> into the scope of a function (e.g. silence()); this said, I still feel this
> would contain similar issues as it wouldn't address the underlying issues
> of lazy error suppression.

I don't see how that would achieve anything but making it more verbose.
The inherent problem is that some error reporting is unneeded in some
contexts, while welcome in others. That's the problem that needs
solving, the syntax is secondary to it.

> Lastly, I recognise this will be a big change to PHP; but I feel it is
> necessary to enhance the quality of PHP error handling. Let's not forget
> that PHP managed to successfully deprecate the MySQL library.

PHP did not just remove mysql library, it replaced it with better
alternative. Which was well in place when the talk of the removal
started. I agree that PHP error system could use a lot of improvement -
in fact, it already started with move to exceptions and other changes -
but it has to go much further before we could afford to remove @. I
would say it definitely should not happen anywhere in 7.x line.

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #89947 — Bishop Bettini — 2015-12-31T21:48:13+00:00

URL: https://externals.io/message/89939#89947 · In reply to: #89946

On Thu, Dec 31, 2015 at 4:10 PM, Stanislav Malyshev <smalyshev@gmail.com>
wrote:

>
> The inherent problem is that some error reporting is unneeded in some
> contexts, while welcome in others. That's the problem that needs
> solving, the syntax is secondary to it.
>

That hits the nail on the head.

When triggered errors are unneeded, @ works beautifully.

When they're needed, use a helper like from my third-party library
<https://github.com/haldayne/fox/blob/master/src/CaptureErrors.php> to
capture them:

use Haldayne\Fox\CaptureErrors;
$copy = new CaptureErrors(function ($a, $b) { return copy($a, $b); });
$okay = $copy('foo.txt', 'bar.txt');
if (! $okay) {
    throw new
RuntimeException($copy->getCapturedErrors()->pop()->get('message'));
}

I am -1 on removing @ for 7.x series.  But, I would be in favor of all
changes that remove unnecessary error messages or add functionality to
better work with error messages. In my mind, those are requisite steps
before removing @.

Thanks,
bishop

---

## #90039 — Andrea Faulds — 2016-01-05T02:18:04+00:00

URL: https://externals.io/message/89939#90039 · In reply to: #89947

Hi Bishop,

Bishop Bettini wrote:
> I am -1 on removing @ for 7.x series.  But, I would be in favor of all
> changes that remove unnecessary error messages or add functionality to
> better work with error messages. In my mind, those are requisite steps
> before removing @.

I agree here.

It'd be nice if we could somehow catch errors in the same way we can 
with exception, but we don't have this just now. Problem is a I can't 
think of a non-messy way to make this work, at least not without going 
through every PHP extension and adding an identifier for different errors.

One improvement, though, might be an @ equivalent that only silences a 
certain level of error. It's still too broad, but it's nonetheless 
better than the silence-all we have now.

Thanks.

-- 
Andrea Faulds
https://ajf.me/

---

## #90043 — Aaron Piotrowski — 2016-01-05T02:52:43+00:00

URL: https://externals.io/message/89939#90043 · In reply to: #89947

Hi Bishop,


> 
> 
> I am -1 on removing @ for 7.x series.  But, I would be in favor of all
> changes that remove unnecessary error messages or add functionality to
> better work with error messages. In my mind, those are requisite steps
> before removing @.
> 

I am also very much in agreement with this. There are many conditions where a warning or other error is raised with no way to test for the condition that will trigger the error. Before the @ can be removed, either these errors need to be removed or they need to become an exception that can be caught. For example, I have the following code for writing to a non-blocking stream (assume $resource is a stream socket resource and $data is a string):

// Error reporting suppressed since `fwrite()` emits `E_WARNING` if the pipe is broken or the buffer is full.
$written = @fwrite($resource, $data);
if (false === $written) {
    $message = 'Failed to write to stream.';
    if ($error = `error_get_last()`) {
        $message .= sprintf(' Errno: %d; %s', $error['type'], $error['message']);
    }
    throw new FailureException($message);
}

There is no way of knowing if the stream buffer is full before calling `fwrite()`, resulting in a warning and 0 being returned. IMO, just 0 should be returned without issuing a warning.

Aaron Piotrowski
https://trowski.com
@trowski2002

---

## #90046 — Sara Golemon — 2016-01-05T03:22:27+00:00

URL: https://externals.io/message/89939#90046 · In reply to: #89946

> I don't think it is a good idea, currently, for the following reasons:
>
[::snip::]

It terrifies me to say this, but I completely agree with Stas. ;)

I can't personally remember the last time I used @ in any production
code, but my one-offs are replete with them.  It's a quintessentially
PHP feature in its pragmatism.

Okay, I'll put the thesaurus down.

-Sara

---

## #90068 — Rasmus Lerdorf — 2016-01-05T05:28:16+00:00

URL: https://externals.io/message/89939#90068 · In reply to: #90046

> 
> > […]
> [::snip::]
> 
> It terrifies me to say this, but I completely agree with Stas. ;)
> 
> I can't personally remember the last time I used @ in any production
> code, but my one-offs are replete with them.  It's a quintessentially
> PHP feature in its pragmatism.
> 
> Okay, I'll put the thesaurus down.

I'd be quite sad to see @ disappear as well. It was one of PHP's
earliest features and its roots date back to mid-80's DOS batch files
(before 1/3 of this list were born I would guess)

-Rasmus

---

## #90069 — Sara Golemon — 2016-01-05T05:45:22+00:00

URL: https://externals.io/message/89939#90069 · In reply to: #89939

> I am looking to submit an RFC in order to remove the error suppression
> operator in PHP, namely the @ symbol.
>
Forwarding a suggestion twitter/@Beryllium9:

How about a global "disable error suppression" setting?  That way a
project lead could enforce it for their codebase (and guarantee that
devs "aren't lazy"), but PHP doesn't lose its pragmatism?

-Sara

---

## #90070 — Sara Golemon — 2016-01-05T05:50:41+00:00

URL: https://externals.io/message/89939#90070 · In reply to: #90069

> 
> > […]
> Forwarding a suggestion twitter/@Beryllium9:
>
> How about a global "disable error suppression" setting?  That way a
> project lead could enforce it for their codebase (and guarantee that
> devs "aren't lazy"), but PHP doesn't lose its pragmatism?
>
And to add to that, we have mechanisms to allow settings to be dialed
one way but not another, so this could be made so that you can always
re-enable suppressed errors, but you can never re-hide them.
(open_basedir does something similar)

-Sara

---

## #90071 — Dustin Wheeler — 2016-01-05T05:52:07+00:00

URL: https://externals.io/message/89939#90071 · In reply to: #90069

Hi, chiming in from the side,


> Forwarding a suggestion twitter/@Beryllium9:
>
> How about a global "disable error suppression" setting?  That way a
> project lead could enforce it for their codebase (and guarantee that
> devs "aren't lazy"), but PHP doesn't lose its pragmatism?
>

I think this is an excellent compromise worth discussion and can vouch
for usage of this suggestion in our environment, today. I maintain a
shared hosting environment of sorts and have many different developer
groups working in that environment. This is the sort of configuration
we would take advantage of immediately.

Thanks twitter/@Beryllium9 (wherever you are!) + Sara,

-- 
Dustin Wheeler | Software Developer
NC State University
m: mdwheele@ncsu.edu | w: 5-9786
"If you don't know where you're going, it's easy to iteratively not get there."

---

## #90080 — Michael Heap — 2016-01-05T10:31:18+00:00

URL: https://externals.io/message/89939#90080 · In reply to: #90069

Sounds like the xdebug.scream or the Scream PECL extension (
https://pecl.php.net/package/scream) to me.

+1 for baking this functionality into core



> 
> > […]
> Forwarding a suggestion twitter/@Beryllium9:
>
> How about a global "disable error suppression" setting?  That way a
> project lead could enforce it for their codebase (and guarantee that
> devs "aren't lazy"), but PHP doesn't lose its pragmatism?
>
> -Sara

---

## #90083 — Derick Rethans — 2016-01-05T10:56:41+00:00

URL: https://externals.io/message/89939#90083 · In reply to: #90080

> 
> 
> 
> > […]

> Sounds like the xdebug.scream or the Scream PECL extension ( 
> https://pecl.php.net/package/scream) to me.
> 
> +1 for baking this functionality into core

That's going to mean an INI setting.. that hosters could abuse. Having 
an INI setting like this as part of core is IMO not a great idea.

cheers,
Derick

-- 
http://derickrethans.nl | http://xdebug.org
Like Xdebug? Consider a donation: http://xdebug.org/donate.php
twitter: @derickr and @xdebug
Posted with an email client that doesn't mangle email: alpine

---

## #90084 — Zeev Suraski — 2016-01-05T11:13:38+00:00

URL: https://externals.io/message/89939#90084 · In reply to: #90068

> -----Original Message-----
> From: Rasmus Lerdorf [mailto:rasmus@lerdorf.com]
> Sent: Tuesday, January 05, 2016 7:28 AM
> To: Sara Golemon; Stanislav Malyshev
> Cc: Junade Ali; PHP internals
> Subject: Re: [PHP-DEV] Deprecation of the Error Control Operator (@
> symbol)
>
> 
> > […]
> <smalyshev@gmail.com> wrote:
> > […]
>
> I'd be quite sad to see @ disappear as well. It was one of PHP's earliest
> features and its roots date back to mid-80's DOS batch files (before 1/3
> of
> this list were born I would guess)

Same here.

Zeev

---

## #90086 — Zeev Suraski — 2016-01-05T11:57:42+00:00

URL: https://externals.io/message/89939#90086 · In reply to: #90083

> -----Original Message-----
> From: Derick Rethans [mailto:derick@php.net]
> Sent: Tuesday, January 05, 2016 12:57 PM
> To: Michael Heap
> Cc: Sara Golemon; Junade Ali; PHP internals
> Subject: Re: [PHP-DEV] Deprecation of the Error Control Operator (@
> symbol)
>
> 
>
> > […]
>
> > […]
>
> That's going to mean an INI setting.. that hosters could abuse. Having
an INI
> setting like this as part of core is IMO not a great idea.

I agree.  Perhaps through a declare() statement instead?  We could easily
make it file-based, so that the declare() statement only affects the local
file, or we could make it global for the entire request.

Zeev

---

## #90088 — Grzegorz Zdanowski — 2016-01-05T12:27:53+00:00

URL: https://externals.io/message/89939#90088 · In reply to: #90086

> > […]
> an INI
> > […]
>
> I agree.  Perhaps through a declare() statement instead?  We could easily
> make it file-based, so that the declare() statement only affects the local
> file, or we could make it global for the entire request.
>
> Zeev
>
> --
> 
> 
>

I can't agree more - it's a pain such thing as @ exists.
However we have a bigger issue here - a lot PHP function returns false
AND raises E_WARNING. fopen, fwrite, fread, stream_select.... a lot of
them which I use daily.

Before deprecating @ operator I think we should make a RFC which cover
unified setting to convert all E_* to exceptions (like
PhpWarningException). I know it's just a temporary solution, because
exception should be more specific, but it's a huge amount of work to
replace all errors and warnings with proper exceptions.
Of course it's possible to convert all errors and warnings to
exceptions using `set_error_handler()`, but it will be next boilerplate
code for all apps.

--
Cheers,
Grzegorz Zdanowski.

---

## #90089 — Rowan Collins — 2016-01-05T13:49:03+00:00

URL: https://externals.io/message/89939#90089 · In reply to: #90088

Grzegorz Zdanowski wrote on 05/01/2016 12:27:
> Before deprecating @ operator I think we should make a RFC which cover
> unified setting to convert all E_* to exceptions (like
> PhpWarningException). I know it's just a temporary solution, because
> exception should be more specific, but it's a huge amount of work to
> replace all errors and warnings with proper exceptions.

This is definitely not the solution. I've seen this suggested a few 
times over the years, and every time people seem to miss a vital point: 
Warnings are not, in general, a fatal situation. A useful rule of thumb 
I heard for "should I throw an exception?" is "would I be happy to use a 
 `die()` statement?"

Even if you don't accept that, the main purpose of an exception is to 
force the code down a different path. (I've seen lots of discussions 
about exceptions being great because they have stack traces, but have 
never understood why any other mechanism couldn't also have those).

In a few places, like the file-handle API, the Warning is accompanied by 
an invalid return value (usually false) and probably should be an 
exception - the code will definitely need to follow a different path, 
and dying would often be better than proceeding with an invalid handle 
(which will probably end up fatal later).

But in many cases, an `E_WARNING` (or an E_NOTICE) really is just a 
warning - most code *doesn't* want to go down an alternative path, but 
it might want to log a message. In a few cases, code does want to go 
down a different path, and currently has to use the "error handler" 
infrastructure. In other cases, code wants to never log the message, and 
currently has to use the @ operator.

The main problem, in my opinion, with the current system of "errors" 
(better called "messages") is that they provide only two pieces of 
identifying information: an integer representing severity, from a small 
list; and a string which may have placeholders, may change between 
versions, and does not come from a documented list. This means you can 
say "suppress everything with `E_NOTICE` severity" but not "suppress all 
array-assignment warnings"; and you can set up an error handler to 
convert everything into exceptions, but a handler to convert all 
file-handle warnings into exceptions would have to pattern-match every 
message string to identify them.

The only way out of this that I can see is to replace the current 
string-based internal message APIs with something that forces the 
extension developer to pre-define a set of codes, and provide the 
substitution parameters for the error directly. This could then allow 
more information to be exposed to userland, and more granular stacking 
of handlers and configuration to mask off different types based on their 
codes.

Regards,
-- 
Rowan Collins
[IMSoP]

---

## #90114 — Andrea Faulds — 2016-01-05T17:37:01+00:00

URL: https://externals.io/message/89939#90114 · In reply to: #90069

Hi Sara,

Sara Golemon wrote:
> 
> > […]
> Forwarding a suggestion twitter/@Beryllium9:
>
> How about a global "disable error suppression" setting?  That way a
> project lead could enforce it for their codebase (and guarantee that
> devs "aren't lazy"), but PHP doesn't lose its pragmatism?

I don't think that would work out too well. Remember that many projects 
have error handles which convert all errors to exceptions: if you 
disable @ in those projects, wouldn't their code break?

Thanks.
-- 
Andrea Faulds
https://ajf.me/

---

## #90116 — Sara Golemon — 2016-01-05T17:48:11+00:00

URL: https://externals.io/message/89939#90116 · In reply to: #90086

> > […]
>
I honestly don't understand why that's a bad idea.  There are a LOT of
settings that hosters could abuse, but as a general rule they don't,
because it breaks client apps and clients leave.

A hoster could just as easily install XDebug and turn that setting on.
Are they doing that?

Or are you, Derick Rethans, suggesting that installing XDebug is a bad idea? ;)

> I agree.  Perhaps through a declare() statement instead?  We could easily
> make it file-based, so that the declare() statement only affects the local
> file, or we could make it global for the entire request.
>
Eh, feels very tomato-tomato to me.  Trading in a line in
php.ini/.htaccess/index.php for a line in index.php.  Ultimately I'm
the wrong person to defend this since I don't personally have a need
for it, I was just trying to offer compromises.

For context, I do believe the person suggesting it was thinking in
terms of "Finding that fatal error that's been supressed."

-Sara

---

## #90117 — Sara Golemon — 2016-01-05T17:53:06+00:00

URL: https://externals.io/message/89939#90117 · In reply to: #90114

> > […]
>
> I don't think that would work out too well. Remember that many projects have
> error handles which convert all errors to exceptions: if you disable @ in
> those projects, wouldn't their code break?
>
Nope.
Supressed errors already reach custom error handlers: https://3v4l.org/TG8aA

-Sara

---

## #90119 — Ferenc Kovacs — 2016-01-05T18:09:32+00:00

URL: https://externals.io/message/89939#90119 · In reply to: #90117

> 
> > […]
> have
> > […]
> Nope.
> Supressed errors already reach custom error handlers:
> https://3v4l.org/TG8aA
>

sure and most projects check the `error_reporting()` level against the $errno
like in the manual:
    if (!(error_reporting() & $errno)) {
        // This error code is not included in error_reporting
        return;
    }

@ changes the `error_reporting()` level for that particular call, so those
custom error handler won't throw exceptions for the suppressed errors but
when you remove/nop @ their code would throwing stuff left and right.

-- 
Ferenc Kovács
@Tyr43l - http://tyrael.hu

---

## #90123 — Sara Golemon — 2016-01-05T18:22:49+00:00

URL: https://externals.io/message/89939#90123 · In reply to: #90119

> > […]
>
> sure and most projects check the `error_reporting()` level against the $errno
> like in the manual:
>     if (!(error_reporting() & $errno)) {
>         // This error code is not included in error_reporting
>         return;
>     }
>
> @ changes the `error_reporting()` level for that particular call, so those
> custom error handler won't throw exceptions for the suppressed errors but
> when you remove/nop @ their code would throwing stuff left and right.
>
Today I learned...  Okay, def a problem (for a specific set of
circumstances).  And one which makes me more amenable to Ze'ev
declare() suggestion (on a per-request bases, not per-file) as anyone
modifying a project's codebase for testing can also modify it to
suppress those exceptions as needed and/or just not enable the custom
error handler.

-Sara

---

## #90138 — Rowan Collins — 2016-01-05T19:40:12+00:00

URL: https://externals.io/message/89939#90138 · In reply to: #90119

Ferenc Kovacs wrote on 05/01/2016 18:09:
> sure and most projects check the `error_reporting()` level against the $errno
> like in the manual:
>      if (!(error_reporting() & $errno)) {
>          // This error code is not included in error_reporting
>          return;
>      }
>
> @ changes the `error_reporting()` level for that particular call, so those
> custom error handler won't throw exceptions for the suppressed errors but
> when you remove/nop @ their code would throwing stuff left and right.

I'm lost - how does this validate the claim that building scream mode 
into core would lead to problems? We already have an ini setting which 
can change the error_reporting level, so any error handler relying on 
that is *already* subject to different behaviour in different 
environments. Any codebase which wants to ignore the settings of the 
environment would surely already omit that boilerplate, and thus be 
unaffected by the presence or functionality of the @ operator.

Regards,
-- 
Rowan Collins
[IMSoP]

---

Next page: https://externals.io/message/89939.md?page=2
