You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
print_r() results in warning: unexpected NAN value was coerced to string #23662
Warning: unexpected NAN value was coerced to string in /in/IW2fE on line 3
Array
(
[0] => NAN
)
But I expected this output instead:
Array
(
[0] => NAN
)
This warning got introduced in #19573 but I don’t think affecting print_r() was intended as this function is supposed to “Print human-readable information about a variable”.
The related functions var_dump() and var_export() are not affected by this warning.
PHP Version
PHP 8.5.8 (cli) (built: Jul 1 2026 03:46:27) (NTS)
Copyright (c) The PHP Group
Built by Homebrew
Zend Engine v4.5.8, Copyright (c) Zend Technologies
with Zend OPcache v8.5.8, Copyright (c), by Zend Technologies
<?phpprint_r([NAN]); // warnsvar_dump(NAN); // does not warnvar_export(NAN); // does not warnechoNAN; // warns
From the RFC:
we propose to emit the following warning when NAN is coerced (be that implicitly or explicitly) to another type:
So based on interpretation this either means that none of the above should emit a warning, or all of them should.
This affects passing NAN as an argument to parameters which do not declare float as a type, all casting operators, logical operators, if statements, and ternary operator.
None of the above fall into this category, so based on this none of them should emit a warning.
It gets more confusing because of different entry points:
<?phpjson_encode([NAN]); // does not warnhttp_build_query(['a'=>NAN]); // warns
This seems inconsistent: I believe they should behave the same way.
This would fix the printing case, but leaves the json/http example inconsistent:
diff --git a/Zend/zend.c b/Zend/zend.c
index aa621c4daa8..c5c220aed38 100644
--- a/Zend/zend.c+++ b/Zend/zend.c@@ -521,6 +521,10 @@ void zend_print_flat_zval_r_to_buf(smart_str *buf, zval *expr) /* {{{ */
case IS_STRING:
smart_str_append(buf, Z_STR_P(expr));
break;
+ case IS_DOUBLE:+ /* Not going through the string coercion as printing a value is not a cast. */+ smart_str_append_double(buf, Z_DVAL_P(expr), (int) EG(precision), false);+ break;
default:
{
zend_string *str = zval_get_string_func(expr);
@@ -597,6 +601,10 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /*
case IS_LONG:
smart_str_append_long(buf, Z_LVAL_P(expr));
break;
+ case IS_DOUBLE:+ /* Not going through the string coercion as printing a value is not a cast. */+ smart_str_append_double(buf, Z_DVAL_P(expr), (int) EG(precision), false);+ break;
case IS_REFERENCE:
zend_print_zval_r_to_buf(buf, Z_REFVAL_P(expr), indent);
break;
It is unclear to me what the intended semantics are, the RFC is underspecified.
The real fix is probably to move the warning to the entry points of coercion rather than deep into the engine itself.
cc @Girgias
TBH the intention was to warn on any coercion, including to string when priting. So the echo behaviour is correct from my PoV. Now I do agree that print_r() is more a debugging function than anything else so should probably behave like var_dump().
The reason json_encode allows NAN is that NAN is a valid value in JSON, but it is not in HTTP.
I do find it confusing, because strictly speaking they all make a conversion to a string
sure but var_dump is a debuging utility, and var_export is meant to export code that can be executed and NAN is a valid PHP float constant. So I don't think those should warn. The question for me is print_r a debugging function or not (IMHO yes).
The reason json_encode allows NAN is that NAN is a valid value in JSON, but it is not in HTTP.
This is false, NAN is not valid in JSON.
TIL, well I guess then yes should be fixed as well.
This actually results in the error Inf and NaN cannot be JSON encoded, so there is probably no fix needed for json_encode(), see https://3v4l.org/Gfpeh#veol
Activity
ndossche commentedon Sep 11, 2026
More specifically:
From the RFC:
So based on interpretation this either means that none of the above should emit a warning, or all of them should.
None of the above fall into this category, so based on this none of them should emit a warning.
It gets more confusing because of different entry points:
This seems inconsistent: I believe they should behave the same way.
This would fix the printing case, but leaves the json/http example inconsistent:
It is unclear to me what the intended semantics are, the RFC is underspecified.
The real fix is probably to move the warning to the entry points of coercion rather than deep into the engine itself.
cc @Girgias
Girgias commentedon Sep 11, 2026
TBH the intention was to warn on any coercion, including to string when priting. So the
echobehaviour is correct from my PoV. Now I do agree thatprint_r()is more a debugging function than anything else so should probably behave likevar_dump().The reason json_encode allows
NANis that NAN is a valid value in JSON, but it is not in HTTP.ndossche commentedon Sep 11, 2026
I do find it confusing, because strictly speaking they all make a conversion to a string
This is false, NAN is not valid in JSON.
Girgias commentedon Sep 12, 2026
sure but var_dump is a debuging utility, and var_export is meant to export code that can be executed and NAN is a valid PHP float constant. So I don't think those should warn. The question for me is print_r a debugging function or not (IMHO yes).
TIL, well I guess then yes should be fixed as well.
ausi commentedon Sep 12, 2026
This actually results in the error
Inf and NaN cannot be JSON encoded, so there is probably no fix needed forjson_encode(), see https://3v4l.org/Gfpeh#veolDanielEScherzer commentedon Sep 12, 2026
Just going to cross link #22683
Fix phpGH-23662: avoid NAN warning in print_r()
Fix phpGH-23662: avoid NAN warning in print_r()