walkor/workerman · error · RuntimeException
The $outputStream must to be a stream, %s given
Error message
The $outputStream must to be a stream, %s given
What it means
Worker::initStdOut() validates the configured output stream: it must be a live resource of type 'stream' (the place Workerman prints status/log output to). When the property holds something else (a string path, an array, a closed resource) it resets to the default stream and throws, naming the wrong type via get_debug_type.
Source
Thrown at src/Worker.php:682
$iniFilePath = (string)php_ini_loaded_file();
exit('Notice: '. implode(',', $disabled) . " are disabled by disable_functions. " . PHP_EOL
. "Please remove them from disable_functions in $iniFilePath" . PHP_EOL);
}
}
/**
* Init stdout.
*
* @return void
*/
protected static function initStdOut(): void
{
$defaultStream = fn () => defined('STDOUT') ? STDOUT : (@fopen('php://stdout', 'w') ?: fopen('php://output', 'w'));
static::$outputStream ??= $defaultStream(); //@phpstan-ignore-line
if (!is_resource(self::$outputStream) || get_resource_type(self::$outputStream) !== 'stream') {
$type = get_debug_type(self::$outputStream);
static::$outputStream = $defaultStream();
throw new RuntimeException(sprintf('The $outputStream must to be a stream, %s given', $type));
}
static::$outputDecorated ??= self::hasColorSupport();
}
/**
* Borrowed from the symfony console
* @link https://github.com/symfony/console/blob/0d14a9f6d04d4ac38a8cea1171f4554e325dae92/Output/StreamOutput.php#L92
*/
private static function hasColorSupport(): bool
{
// Follow https://no-color.org/
if (getenv('NO_COLOR') !== false) {
return false;
}
if (getenv('TERM_PROGRAM') === 'Hyper') {
return true;View on GitHub (pinned to 1391112a61)
Solutions
- Assign a real resource: Worker::setStdOut(fopen('/var/log/app.log', 'a')) or leave it unset to use the default STDOUT
- If the stream comes from config, fopen() it first and check the result is a resource before assigning
- Do not close the stream you assigned; Workerman owns it for the process lifetime
Example fix
// before
Worker::$outputStream = '/var/log/app.log'; // string -> throws 'must be a stream, string given'
// after
Worker::setStdOut(fopen('/var/log/app.log', 'a')); Defensive patterns
Strategy: validation
Validate before calling
$stream = fopen('/var/log/app.log', 'a');
if ($stream === false || !is_resource($stream) || get_resource_type($stream) !== 'stream') {
throw new RuntimeException('cannot open log stream, keeping default stdout');
}
Worker::setStdOut($stream); Type guard
function isUsableOutputStream(mixed $s): bool
{
return is_resource($s) && get_resource_type($s) === 'stream';
} Prevention
- Never assign a path string to Worker::$outputStream; fopen() it and check the result first
- Let Workerman own the stream: do not fclose() it in your own shutdown code
When it happens
Trigger: Setting Worker::$outputStream = 'php://stdout' or a file path string instead of a resource; assigning the result of a wrapper that returned false/null; passing a resource that was fclose()'d before Worker::runAll(); Worker::setStdOut() called with a non-resource.
Common situations: Trying to redirect worker output to a log file by assigning a path string; refactoring that swaps STDOUT (constant, resource) for a configurable value that arrives as a string from config; double-closing the stream in custom shutdown code.
Related errors
- %s::$eventLoopClass must implement %s
- Bad remoteAddress
- Invalid protocol scheme '$scheme'
- class \Protocols\$scheme not exist
- Invalid protocol scheme '$scheme'
AI-assisted analysis of walkor/workerman@1391112a61 (2026-08-21).
Data as JSON: /api/errors/6f06618533df12a1.
Report an issue: GitHub.