getgrav/grav · error · InvalidArgumentException
Uri host must be a string
Error message
Uri host must be a string
What it means
UriPartsFilter::filterHost() asserts the host is a string before normalizing (IPv6 bracketing, hostname regex, lowercasing), throwing InvalidArgumentException otherwise. It backs AbstractUri::withHost() and the Uri parts constructor; since withHost() declares a native `string` parameter, the is_string throw is mostly reachable via direct filterHost() calls or untyped callers passing null/array.
Source
Thrown at system/src/Grav/Framework/Uri/UriPartsFilter.php:66
throw new InvalidArgumentException('Uri user info must be a string');
}
return preg_replace_callback(
'/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=]+|%(?![A-Fa-f0-9]{2}))/u',
fn($match) => rawurlencode((string) $match[0]),
$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|nullView on GitHub (pinned to 6040efed04)
Solutions
- Default the host: `$host = $headerHost ?? 'localhost'`
- Cast scalar values to string before filtering
- Use `$uri->withHost((string) $host)` so failures surface as a clear TypeError at the typed boundary
Example fix
// before $host = UriPartsFilter::filterHost($env['HTTP_HOST'] ?? null); // CLI: null -> throws // after $host = UriPartsFilter::filterHost((string) ($env['HTTP_HOST'] ?? 'localhost'));
Defensive patterns
Strategy: type-guard
Validate before calling
$host = $env['HTTP_HOST'] ?? $env['SERVER_NAME'] ?? 'localhost';
if (!is_string($host)) {
throw new \InvalidArgumentException('host must be a string');
} Type guard
function isHostString(mixed $value): bool
{
return is_string($value) && $value !== '';
} Prevention
- Always default host-derived values ('localhost') for CLI/synthetic requests
- Cast header values to string at the trust boundary
- Use withHost() so type errors surface at the typed API edge
When it happens
Trigger: Calling filterHost(null) when a Host header is absent; passing an array from a malformed parse result; feeding `$env['HTTP_HOST']` derived value that was never cast when calling the filter directly.
Common situations: Middleware reading Host/X-Forwarded-Host headers that may be missing on CLI or synthetic requests; building test fixtures where the host field was left null.
Related errors
- URL must be a string
- Uri scheme must be a string
- Uri user info must be a string
- Uri host name validation failed
- Uri port must be null or an integer between 0 and 65535
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/eb0372da70f8cb21.
Report an issue: GitHub.