Description
When get_headers() fails to retrieve headers for a syntactically valid URL (network/DNS/connection failure), the function both returns false and emits a PHP Warning coming from the underlying stream wrapper. In environments where warnings are globally converted to exceptions or centrally reported, this behavior is noisy and often undesirable for simple availability checks. The user expectation for a "headers existence check" is: reachable → return headers; unreachable → return false (no diagnostic noise).
Steps to reproduce:
Run PHP code with error reporting that converts warnings to exceptions, or with centralized reporting enabled.
Call get_headers('http://10.255.255.1/somepath') (an IP that will not respond) or any valid URL that is unreachable due to network/DNS.
Observe: a PHP Warning such as "failed to open stream: Connection refused" is emitted in addition to the function returning false.
Minimal repro:
// Example environment: convert warnings to ErrorException
set_error_handler(function($errno, $errstr, $errfile, $errline) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});
var_dump(@get_headers('http://10.255.255.1/')); // even with @, global handler may intercept
// or without @:
// var_dump(get_headers('http://10.255.255.1/'));
Actual behavior:
get_headers() triggers a PHP Warning from the underlying stream wrapper and then returns false. In systems that convert warnings to exceptions this leads to exceptions being thrown for otherwise expected "false" outcomes.
Expected behavior (user intent):
For an API that is frequently used as a boolean availability check, it would be safer if get_headers() either:
a) did not emit a Warning for normal network unreachable conditions and simply returned false; or
b) provided an explicit, documented option/flag to request "silent failure" semantics (no warnings), or
c) documented clearly that the stream wrapper may emit warnings and recommended alternatives (such as cURL) — and ideally made the distinction clear in the main Description/Return Values text.
Rationale:
Many callers use get_headers() for availability checks where a simple false is sufficient. Emitting warnings forces applications to implement local suppression or to use fragile error handler hacks; it also breaks systems that treat warnings as exceptions for centralized error handling.
Suggested mitigations / patch ideas:
Add a parameter or context option to get_headers() to request "silent" failure (no warnings), or
Make the manual page explicitly document this warning behavior in the main Description and add best-practice guidance (e.g., prefer cURL for predictable timeouts and silent failure in production), or
Modify stream wrapper behavior so that get_headers() failures due to network unreachable conditions are not surfaced as warnings at the PHP level (treat them as normal return=false cases).
Environment:
Observed across multiple PHP 7/8 versions where the HTTP stream wrapper is used. Behaviors vary with allow_url_fopen, stream wrapper implementation and PHP version; historical bugs affecting timeouts and HTTPS behavior exist (see bug 41631 and other notes).
Notes:
This is not about removing diagnostics for all failures; the concern is that a simple availability check becomes noisy and can trigger global error handlers unexpectedly. A controlled option for silent-fail semantics or clearer documentation would help users avoid fragile suppression workarounds.
PHP Version
PHP 8.5.4 (cli) (built: Mar 10 2026 23:30:42) (ZTS Visual C++ 2022 x64)
Copyright (c) The PHP Group
Built by The PHP Group
Zend Engine v4.5.4, Copyright (c) Zend Technologies
with Zend OPcache v8.5.4, Copyright (c), by Zend Technologies
Operating System
windows 11
Description
When get_headers() fails to retrieve headers for a syntactically valid URL (network/DNS/connection failure), the function both returns false and emits a PHP Warning coming from the underlying stream wrapper. In environments where warnings are globally converted to exceptions or centrally reported, this behavior is noisy and often undesirable for simple availability checks. The user expectation for a "headers existence check" is: reachable → return headers; unreachable → return false (no diagnostic noise).
Steps to reproduce:
Run PHP code with error reporting that converts warnings to exceptions, or with centralized reporting enabled.
Call get_headers('http://10.255.255.1/somepath') (an IP that will not respond) or any valid URL that is unreachable due to network/DNS.
Observe: a PHP Warning such as "failed to open stream: Connection refused" is emitted in addition to the function returning false.
Minimal repro:
// Example environment: convert warnings to ErrorException
set_error_handler(function($errno, $errstr, $errfile, $errline) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});
var_dump(@get_headers('http://10.255.255.1/')); // even with @, global handler may intercept
// or without @:
// var_dump(get_headers('http://10.255.255.1/'));
Actual behavior:
get_headers() triggers a PHP Warning from the underlying stream wrapper and then returns false. In systems that convert warnings to exceptions this leads to exceptions being thrown for otherwise expected "false" outcomes.
Expected behavior (user intent):
For an API that is frequently used as a boolean availability check, it would be safer if get_headers() either:
a) did not emit a Warning for normal network unreachable conditions and simply returned false; or
b) provided an explicit, documented option/flag to request "silent failure" semantics (no warnings), or
c) documented clearly that the stream wrapper may emit warnings and recommended alternatives (such as cURL) — and ideally made the distinction clear in the main Description/Return Values text.
Rationale:
Many callers use get_headers() for availability checks where a simple false is sufficient. Emitting warnings forces applications to implement local suppression or to use fragile error handler hacks; it also breaks systems that treat warnings as exceptions for centralized error handling.
Suggested mitigations / patch ideas:
Add a parameter or context option to get_headers() to request "silent" failure (no warnings), or
Make the manual page explicitly document this warning behavior in the main Description and add best-practice guidance (e.g., prefer cURL for predictable timeouts and silent failure in production), or
Modify stream wrapper behavior so that get_headers() failures due to network unreachable conditions are not surfaced as warnings at the PHP level (treat them as normal return=false cases).
Environment:
Observed across multiple PHP 7/8 versions where the HTTP stream wrapper is used. Behaviors vary with allow_url_fopen, stream wrapper implementation and PHP version; historical bugs affecting timeouts and HTTPS behavior exist (see bug 41631 and other notes).
Notes:
This is not about removing diagnostics for all failures; the concern is that a simple availability check becomes noisy and can trigger global error handlers unexpectedly. A controlled option for silent-fail semantics or clearer documentation would help users avoid fragile suppression workarounds.
PHP Version
Operating System
windows 11