serbanghita/Mobile-Detect · error · MobileDetectException
INVALID_USER_AGENT_ERR
INVALID_USER_AGENT_ERR
Error message
No valid user-agent has been set.
What it means
isMobile() requires a User-Agent to have been set: hasUserAgent() (src/MobileDetect.php:1271) returns true only when the userAgent property is a string, so null throws MobileDetectException with code INVALID_USER_AGENT_ERR (0x1) before any detection runs. With the default 'autoInitOfHttpHeaders' => true the constructor pulls $_SERVER['HTTP_USER_AGENT'], so this mainly fires when auto-init is disabled or no such header exists in the environment. An empty-string UA does not throw — isMobile() returns false for it.
Source
Thrown at src/MobileDetect.php:1412
if (!str_starts_with($name, 'is')) {
throw new BadMethodCallException("No such method exists: $name");
}
$ruleName = substr($name, 2);
return $this->is($ruleName);
}
/**
* Check if the device is mobile.
* Returns true if any type of mobile device detected, including special ones
* @return bool
* @throws MobileDetectException
*/
public function isMobile(): bool
{
if (!$this->hasUserAgent()) {
throw new MobileDetectException('No valid user-agent has been set.', MobileDetectExceptionCode::INVALID_USER_AGENT_ERR);
}
if ($this->isUserAgentEmpty()) {
return false;
}
// Cache check.
try {
$cacheKey = $this->createCacheKey("mobile");
$cacheItem = $this->cache->get($cacheKey);
if ($cacheItem !== null) {
return $cacheItem;
}
// Special case: Amazon CloudFront mobile viewer
if (
$this->getUserAgent() === static::$cloudFrontUA &&
$this->getHttpHeader('HTTP_CLOUDFRONT_IS_MOBILE_VIEWER') === 'true'View on GitHub (pinned to 6ab7b0404d)
Solutions
- Set the UA before detection: $detect->setUserAgent($request->headers->get('User-Agent', '')); pull it from the Request object, not $_SERVER.
- If you disable autoInit for performance (as the config comment suggests), make setUserAgent() part of your per-request bootstrap.
- For genuinely optional detection, guard first: if ($detect->hasUserAgent()) { ... } — or pass '' to get a deterministic false.
Example fix
// before
$detect = new MobileDetect(['autoInitOfHttpHeaders' => false]);
$detect->isMobile(); // throws: No valid user-agent has been set.
// after
$detect = new MobileDetect(['autoInitOfHttpHeaders' => false]);
$detect->setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) ...');
$detect->isMobile(); // bool Defensive patterns
Strategy: validation
Validate before calling
if (!$detect->hasUserAgent()) {
$detect->setUserAgent($request->headers->get('User-Agent', ''));
}
$isMobile = $detect->isMobile(); // no longer throws for missing UA Type guard
// MobileDetect::hasUserAgent(): bool is the built-in guard — call it first
if ($detect->hasUserAgent() && !$detect->isUserAgentEmpty()) {
$isMobile = $detect->isMobile();
} Try / catch
use Detection\Exception\MobileDetectException;
use Detection\Exception\MobileDetectExceptionCode;
try {
$isMobile = $detect->isMobile();
} catch (MobileDetectException $e) {
if ($e->getCode() === MobileDetectExceptionCode::INVALID_USER_AGENT_ERR) {
$isMobile = false; // no UA available; treat as non-mobile
} else {
throw $e;
}
} Prevention
- Centralize detector construction in middleware: create, setUserAgent from the Request, run checks — one place, correct order.
- If you disable autoInitOfHttpHeaders you own UA injection; pair it with setUserAgent in the same bootstrap.
- Seed $_SERVER['HTTP_USER_AGENT'] in CLI tests so CI matches web behavior.
When it happens
Trigger: Constructing with ['autoInitOfHttpHeaders' => false] and never calling setUserAgent(); running in CLI, queue workers, cron or PHPUnit where $_SERVER['HTTP_USER_AGENT'] is absent; long-running runtimes (Octane, Swoole, RoadRunner, FrankenPHP worker) where the detector is built before a request exists; calling isMobile() on a fresh instance in a test without a UA fixture.
Common situations: Upgrading from 2.x, where isMobile() silently returned false for a missing UA — 4.x makes it an explicit error, so legacy paths that never set a UA start throwing; framework batch jobs and CI pipelines where the HTTP superglobals are never populated; API-to-API endpoints where the client sends no User-Agent header.
Related errors
- No such method exists: $name
- IS_MOBILE_ERR
- cacheKeyFn is not a function.
- Cache key must be a string.
- Invalid key: '$key'. Must be alphanumeric, can contain _ and
AI-assisted analysis of serbanghita/Mobile-Detect@6ab7b0404d (2026-08-21).
Data as JSON: /api/errors/9cbea5070c60b9dd.
Report an issue: GitHub.