flarum/framework · warning

[$errno] $errstr in $errfile:$errline

Error message

[$errno] $errstr in $errfile:$errline

What it means

ServeCommand's custom PHP error handler intercepts PHP warnings/notices/deprecations raised while the websocket server runs. For low-severity levels (E_DEPRECATED, E_USER_DEPRECATED, E_NOTICE, E_USER_NOTICE) it does NOT convert them to exceptions; in --debug mode it instead logs `[$errno] $errstr in $errfile:$errline` and returns true to suppress PHP's default handling. Higher severities are still thrown as exceptions.

Solutions

  1. Update the package/file named in $errfile to a version compatible with your PHP version.
  2. If the deprecation comes from your own code, replace the deprecated call per the message.
  3. Run without --debug in production if the log noise is undesirable (still fix the source).
  4. Confirm the message is only a deprecation/notice (errno in the low-severity set) — otherwise it would have thrown.
  5. Pin a known-good PHP version for the server process.

Example fix

// before (PHP 8.2)
$strpos = strpos($haystack, $needle, null);
// after
$strpos = strpos($haystack, $needle);
Defensive patterns

Strategy: fallback

Validate before calling

// Before running the server, scan for known deprecations:
$report = error_reporting(E_ALL);
set_error_handler(function ($no, $str, $file) { var_dump([$no, $str, $file]); return true; });
require 'vendor/autoload.php';
restore_error_handler();

Type guard

$lowSeverity = in_array($errno, [E_DEPRECATED, E_USER_DEPRECATED, E_NOTICE, E_USER_NOTICE], true);
if (!$lowSeverity) { throw new ErrorException($errstr, 0, $errno, $errfile, $errline); }

Try / catch

try {
  $server->run();
} catch (ErrorException $e) {
  $this->logger->warning(sprintf('[%d] %s in %s:%d', $e->getSeverity(), $e->getMessage(), $e->getFile(), $e->getLine()));
}

Prevention

When it happens

Trigger: Running the realtime/websocket serve command (with --debug) triggers PHP code that emits a deprecation, notice, or warning — e.g. deprecated function usage in bundled dependencies or userland notices — producing this log line.

Common situations: PHP 8.x upgrades making previously-silent deprecations loud (e.g. dynamic properties, null-to-non-nullable args); outdated packages not yet compatible with the PHP version; debug mode enabled so the messages become visible.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


AI-assisted analysis of flarum/framework@4b939f6853 (2026-09-15). Data as JSON: /api/errors/0a7692b7ec41efbb. Report an issue: GitHub.

Appendix: source

Thrown at extensions/realtime/src/Websocket/Console/ServeCommand.php:123

            return (new WebsocketLogger($this->output))
                ->enable($debug)
                ->verbose($this->output->isVerbose());
        });

        $this->getLaravel()->bind(ConnectionLogger::class, function () use ($debug) {
            return (new ConnectionLogger($this->output))
                ->enable($debug)
                ->verbose($this->output->isVerbose());
        });
    }

    public function errorHandler(int $errno, string $errstr, string $errfile, int $errline): bool
    {
        // Don't throw exceptions for deprecation notices, warnings, or notices in debug mode
        // Just log them to output instead
        if (in_array($errno, [E_DEPRECATED, E_USER_DEPRECATED, E_NOTICE, E_USER_NOTICE])) {
            if ($this->option('debug')) {
                $this->warn("[$errno] $errstr in $errfile:$errline");
            }

            return true;
        }

        // Throw exceptions for actual errors
        throw new \Exception("$errno, $errstr, $errfile:$errline");
    }

    /**
     * Expire stale index-typing presence and emit falling-edge "stopped typing"
     * signals, so list dots clear without each client running its own per-discussion
     * timer. Swept faster than the TTL (6s) to keep the clear-lag small.
     */
    protected function sweepIndexTyping(LoopInterface $loop): void
    {
        $presence = $this->getLaravel()->make(IndexTypingPresence::class);

View on GitHub (pinned to 4b939f6853)