getgrav/grav · error · InvalidArgumentException
Uri host name validation failed
Error message
Uri host name validation failed
What it means
After the is_string check, filterHost() validates the value: a bare IPv6 address gets bracketed, but any other non-empty host must match HOSTNAME_REGEX (labels of alphanumerics/hyphens joined by dots) or InvalidArgumentException 'Uri host name validation failed' is thrown. Notably the regex rejects underscores, empty labels (double dots, leading/trailing dot), and labels starting/ending with a hyphen. IPv4 passes because numeric labels satisfy the pattern.
Source
Thrown at system/src/Grav/Framework/Uri/UriPartsFilter.php:72
$info
) ?? '';
}
/**
* @param string $host
* @return string
* @throws InvalidArgumentException If the host is invalid.
*/
public static function filterHost($host)
{
if (!is_string($host)) {
throw new InvalidArgumentException('Uri host must be a string');
}
if (filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$host = '[' . $host . ']';
} elseif ($host && preg_match(static::HOSTNAME_REGEX, $host) !== 1) {
throw new InvalidArgumentException('Uri host name validation failed');
}
return strtolower($host);
}
/**
* Filter Uri port.
*
* This method
*
* @param int|null $port
* @return int|null
* @throws InvalidArgumentException If the port is invalid.
*/
public static function filterPort($port = null)
{
if (null === $port || (is_int($port) && ($port >= 0 && $port <= 65535))) {
return $port;View on GitHub (pinned to 6040efed04)
Solutions
- Replace underscores with hyphens in the hostname (underscores are invalid in RFC hostnames)
- Split off the port before filtering: `[$host, $port] = explode(':', $host . ':')` and pass the port to withPort()
- Strip a trailing dot and re-check labels if you accept FQDNs from DNS output
- Validate/sanitize Host-derived input from headers before building Uris
Example fix
// before
$uri = $uri->withHost('my_site.local:8080'); // underscore + port -> validation failed
// after
$host = str_replace('_', '-', 'my_site.local');
$uri = $uri->withHost($host)->withPort(8080); Defensive patterns
Strategy: validation
Validate before calling
function isAcceptableHost(string $host): bool
{
$host = rtrim($host, '.'); // tolerate FQDN trailing dot
return $host === ''
|| (bool) filter_var($host, FILTER_VALIDATE_IP)
|| preg_match('/^(?=.{1,253}$)([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)*[a-z0-9]([a-z0-9-]*[a-z0-9])?$/i', $host) === 1;
} Try / catch
try {
$uri = $uri->withHost($host);
} catch (\InvalidArgumentException $e) {
// 'Uri host name validation failed' — sanitize or reject the host
$uri = $uri->withHost('localhost'); // or throw 400 for user-supplied hosts
} Prevention
- Reject underscores in hostnames at the config/DNS level — use hyphens
- Split 'host:port' before calling withHost(); pass the port to withPort()
- Validate Host/X-Forwarded-Host header values against a hostname pattern before building URIs
- Strip trailing dots from DNS-derived FQDNs
When it happens
Trigger: Hostnames containing underscores (`my_site.local`, Docker aliases like `my_app_1`); a host with a trailing dot (`example.com.`); passing `host:port` together so the colon fails the regex; labels with leading/trailing hyphens; hosts built from unvalidated header input containing spaces or slashes.
Common situations: Internal/dev hostnames with underscores (technically invalid per RFC but common in DNS and Docker); misconfigured SERVER_NAME/HTTP_HOST; proxies forwarding a malformed Host header; code passing an unsplit 'example.com:8080' into withHost().
Related errors
- Uri host must be a string
- URL must be a string
- Malformed URL: {$url}
- Uri scheme must be a string
- Uri user info must be a string
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/4632641822dc8047.
Report an issue: GitHub.