sebastianbergmann/phpunit · error · PHPUnit\TextUI\InvalidSocketException

"%s" does not match "socket://hostname:port" format

Error message

"%s" does not match "socket://hostname:port" format

What it means

DefaultPrinter accepts php://, socket://, and plain file targets for output options such as --log-teamcity, --log-junit, --testdox-text, and --testdox-html. For socket:// targets it strips the scheme, explodes on ':' and requires exactly two parts (host, port); any other count throws InvalidSocketException. Missing ports, extra colons, and IPv6 literals (which contain multiple colons, e.g. socket://[::1]:9000) all fail this check. A syntactically valid host:port that cannot be connected to is reported separately by CannotOpenSocketException.

Source

Thrown at src/TextUI/Output/Printer/DefaultPrinter.php:84

    public static function standardError(): self
    {
        return new self('php://stderr');
    }

    /**
     * @throws CannotOpenSocketException
     * @throws DirectoryDoesNotExistException
     * @throws InvalidSocketException
     */
    private function __construct(string $out)
    {
        $this->isPhpStream = str_starts_with($out, 'php://');

        if (str_starts_with($out, 'socket://')) {
            $tmp = explode(':', str_replace('socket://', '', $out));

            if (count($tmp) !== 2) {
                throw new InvalidSocketException($out);
            }

            $stream = @fsockopen($tmp[0], (int) $tmp[1]);

            if ($stream === false) {
                throw new CannotOpenSocketException($tmp[0], (int) $tmp[1]);
            }

            $this->stream = $stream;
            $this->isOpen = true;

            return;
        }

        if (!$this->isPhpStream && !Filesystem::createDirectory(dirname($out))) {
            throw new DirectoryDoesNotExistException(dirname($out));
        }

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Use the exact form socket://hostname:port, e.g. `--log-teamcity socket://localhost:9514`
  2. For IPv6, use a hostname (DNS name) that resolves to the v6 address instead of the literal
  3. Default the port in CI: `socket://collector.example.com:${LOG_PORT:-9514}`

Example fix

# before
vendor/bin/phpunit --log-teamcity socket://localhost

# after
vendor/bin/phpunit --log-teamcity socket://localhost:9514
Defensive patterns

Strategy: validation

Validate before calling

/** True when DefaultPrinter will accept the target (host:port exactly, no IPv6 literal). */
function validSocketTarget(string $target): bool
{
    if (!str_starts_with($target, 'socket://')) {
        return true; // php:// and file paths take another code path
    }

    $parts = explode(':', substr($target, strlen('socket://')));

    return count($parts) === 2
        && $parts[0] !== ''
        && is_numeric($parts[1])
        && (int) $parts[1] > 0;
}

// before passing --log-teamcity / --log-junit / --testdox-* targets:
if (!validSocketTarget($target)) {
    $target = 'socket://collector.example.com:9514'; // or abort
}

Try / catch

try {
    $printer = \PHPUnit\TextUI\Output\DefaultPrinter::from($target);
} catch (\PHPUnit\TextUI\Output\InvalidSocketException $e) {
    // malformed socket://host:port; fix the string (add/repair the port, avoid IPv6 literals)
} catch (\PHPUnit\TextUI\Output\CannotOpenSocketException $e) {
    // well-formed but unreachable: start the collector or fix DNS/firewall, then retry
}

Prevention

When it happens

Trigger: `--log-teamcity socket://localhost` (no port); `socket://logs.example.com:9514:extra`; `socket://[::1]:9514` (IPv6 literal splits into 3 parts); trailing colon `socket://host:`. Note PHPUnit itself catches InvalidSocketException for --log-teamcity and downgrades it to a PHPUnit warning, but direct users of the printer API get the exception.

Common situations: Shipping test results to a log collector (Logstash/Graphite-style TCP input) and forgetting the port; attempting IPv6 endpoints, which this simple parser does not support; port supplied as an empty CI variable.

Related errors


AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23). Data as JSON: /api/errors/22fa8da0c216e6dd. Report an issue: GitHub.