{"record":{"id":"9cbea5070c60b9dd","repo":"serbanghita/Mobile-Detect","slug":"invalid-user-agent-err","errorCode":"INVALID_USER_AGENT_ERR","errorMessage":"No valid user-agent has been set.","messagePattern":"No valid user-agent has been set\\.","errorType":"exception","errorClass":"MobileDetectException","httpStatus":null,"severity":"error","filePath":"src/MobileDetect.php","lineNumber":1412,"sourceCode":"        if (!str_starts_with($name, 'is')) {\n            throw new BadMethodCallException(\"No such method exists: $name\");\n        }\n\n        $ruleName = substr($name, 2);\n\n        return $this->is($ruleName);\n    }\n\n    /**\n     * Check if the device is mobile.\n     * Returns true if any type of mobile device detected, including special ones\n     * @return bool\n     * @throws MobileDetectException\n     */\n    public function isMobile(): bool\n    {\n        if (!$this->hasUserAgent()) {\n            throw new MobileDetectException('No valid user-agent has been set.', MobileDetectExceptionCode::INVALID_USER_AGENT_ERR);\n        }\n\n        if ($this->isUserAgentEmpty()) {\n            return false;\n        }\n\n        // Cache check.\n        try {\n            $cacheKey = $this->createCacheKey(\"mobile\");\n            $cacheItem = $this->cache->get($cacheKey);\n            if ($cacheItem !== null) {\n                return $cacheItem;\n            }\n\n            // Special case: Amazon CloudFront mobile viewer\n            if (\n                $this->getUserAgent() === static::$cloudFrontUA &&\n                $this->getHttpHeader('HTTP_CLOUDFRONT_IS_MOBILE_VIEWER') === 'true'","sourceCodeStart":1394,"sourceCodeEnd":1430,"githubUrl":"https://github.com/serbanghita/Mobile-Detect/blob/6ab7b0404df1da8da2aa2c56634362842d9c2a23/src/MobileDetect.php#L1394-L1430","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n$detect = new MobileDetect(['autoInitOfHttpHeaders' => false]);\n$detect->isMobile(); // throws: No valid user-agent has been set.\n\n// after\n$detect = new MobileDetect(['autoInitOfHttpHeaders' => false]);\n$detect->setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) ...');\n$detect->isMobile(); // bool","handlingStrategy":"validation","validationCode":"if (!$detect->hasUserAgent()) {\n    $detect->setUserAgent($request->headers->get('User-Agent', ''));\n}\n$isMobile = $detect->isMobile(); // no longer throws for missing UA","typeGuard":"// MobileDetect::hasUserAgent(): bool is the built-in guard — call it first\nif ($detect->hasUserAgent() && !$detect->isUserAgentEmpty()) {\n    $isMobile = $detect->isMobile();\n}","tryCatchPattern":"use Detection\\Exception\\MobileDetectException;\nuse Detection\\Exception\\MobileDetectExceptionCode;\n\ntry {\n    $isMobile = $detect->isMobile();\n} catch (MobileDetectException $e) {\n    if ($e->getCode() === MobileDetectExceptionCode::INVALID_USER_AGENT_ERR) {\n        $isMobile = false; // no UA available; treat as non-mobile\n    } else {\n        throw $e;\n    }\n}","preventionTips":["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."],"tags":["user-agent","initialization","mobile-detect","fail-fast","php"],"backgroundTag":"missing-user-agent","analyzedSha":"6ab7b0404df1da8da2aa2c56634362842d9c2a23","analyzedAt":"2026-08-21T04:49:48.090Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}