{"record":{"id":"d8b5621fb0434e15","repo":"serbanghita/Mobile-Detect","slug":"is-mobile-err","errorCode":"IS_MOBILE_ERR","errorMessage":"Cache problem in isMobile(): {$e->getMessage()}","messagePattern":"Cache problem in isMobile\\(\\): (.+?)","errorType":"exception","errorClass":"MobileDetectException","httpStatus":null,"severity":"error","filePath":"src/MobileDetect.php","lineNumber":1445,"sourceCode":"            // Special case: Amazon CloudFront mobile viewer\n            if (\n                $this->getUserAgent() === static::$cloudFrontUA &&\n                $this->getHttpHeader('HTTP_CLOUDFRONT_IS_MOBILE_VIEWER') === 'true'\n            ) {\n                $this->cache->set($cacheKey, true, $this->config['cacheTtl']);\n                return true;\n            }\n\n            if ($this->hasHttpHeaders() && $this->checkHttpHeadersForMobile()) {\n                $this->cache->set($cacheKey, true, $this->config['cacheTtl']);\n                return true;\n            } else {\n                $result = $this->matchUserAgentWithFirstFoundMatchingRule();\n                $this->cache->set($cacheKey, $result, $this->config['cacheTtl']);\n                return $result;\n            }\n        } catch (CacheInvalidArgumentException | CacheException | PsrInvalidArgumentException $e) {\n            throw new MobileDetectException(\"Cache problem in isMobile(): {$e->getMessage()}\", MobileDetectExceptionCode::IS_MOBILE_ERR, $e);\n        }\n    }\n\n    /**\n     * Check if the device is a tablet.\n     * Return true if any type of tablet device is detected.\n     * @return bool\n     * @throws MobileDetectException\n     */\n    public function isTablet(): bool\n    {\n        if (!$this->hasUserAgent()) {\n            throw new MobileDetectException('No user-agent has been set.', MobileDetectExceptionCode::INVALID_USER_AGENT_ERR);\n        }\n\n        if ($this->isUserAgentEmpty()) {\n            return false;\n        }","sourceCodeStart":1427,"sourceCodeEnd":1463,"githubUrl":"https://github.com/serbanghita/Mobile-Detect/blob/6ab7b0404df1da8da2aa2c56634362842d9c2a23/src/MobileDetect.php#L1427-L1463","documentation":"isMobile() wraps every cache interaction (createCacheKey(), cache->get(), cache->set()) in a try/catch and re-throws cache-layer failures — CacheException, CacheInvalidArgumentException, or a PSR Psr\\SimpleCache\\InvalidArgumentException — as MobileDetectException with code IS_MOBILE_ERR (0x2), chaining the original as previous and embedding its message. With the default setup (in-memory Cache + 'sha1' key fn) this is nearly unreachable; it appears when the cache layer was swapped or misconfigured.","triggerScenarios":"Configuring 'cacheKeyFn' to a non-callable (you then see the inner 'cacheKeyFn is not a function.' from createCacheKey, src/MobileDetect.php:1733, wrapped in this message); replacing the PSR-16 cache with a custom Redis/Memcached/filesystem adapter whose get() or set() throws a PSR InvalidArgumentException; a custom cacheKeyFn returning keys that violate /^[A-Za-z0-9_.]{1,64}$/, making the bundled Cache reject them on every call.","commonSituations":"Integrating a PSR-6-to-PSR-16 bridge or Symfony Cache adapter with stricter key rules; DI wiring that injects the wrong service into the cache slot; production-only cache backends failing (connection down, serialization error) while dev used the default in-memory cache and never exercised the path.","solutions":["Inspect the chained exception: $e->getPrevious()->getMessage() names the real cache problem — fix that root cause first.","Keep 'cacheKeyFn' as 'sha1' (or md5 / a hash() closure) so keys always satisfy the bundled Cache's charset and length rule.","Verify any injected CacheInterface is PSR-16 compliant: get($key, $default), set($key, $value, $ttl) with int|DateInterval|null TTL, throwing Psr\\SimpleCache\\InvalidArgumentException for bad arguments only.","If detection must never hard-fail, catch MobileDetectException, match IS_MOBILE_ERR, and fall back to a default or a cache-less detector instance."],"exampleFix":"// before\n$detect = new MobileDetect(['cacheKeyFn' => 'base64']); // not a real function\n$detect->isMobile();\n// MobileDetectException: Cache problem in isMobile(): cacheKeyFn is not a function.\n\n// after\n$detect = new MobileDetect(); // default 'sha1'\ntry {\n    $isMobile = $detect->isMobile();\n} catch (MobileDetectException $e) {\n    if ($e->getCode() === MobileDetectExceptionCode::IS_MOBILE_ERR) {\n        $isMobile = false; // degrade gracefully; log $e->getPrevious()\n    } else {\n        throw $e;\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Prevent the common root cause before detection:\n$config = ['cacheKeyFn' => 'sha1'];\nif (isset($customFn) && !is_callable($customFn)) {\n    throw new \\InvalidArgumentException('cacheKeyFn must be callable, e.g. sha1');\n}\n$detect = new MobileDetect($config);","typeGuard":"function detectorCacheConfigIsSafe(array $config): bool\n{\n    $fn = $config['cacheKeyFn'] ?? 'sha1';\n    if (!is_callable($fn)) { return false; }\n    $sample = $fn('probe:Mozilla/5.0 (X) HTTP_ACCEPT=text/html');\n    return is_string($sample) && preg_match('/^[A-Za-z0-9_.]{1,64}$/', $sample) === 1;\n}","tryCatchPattern":"catch (MobileDetectException $e) {\n    if ($e->getCode() === MobileDetectExceptionCode::IS_MOBILE_ERR) {\n        // cache layer failed; $e->getPrevious() holds the CacheException details\n        $isMobile = false; // or retry with a fresh in-memory detector\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Keep the default sha1 cacheKeyFn unless you must customize; any hash callback works.","Smoke-test custom PSR-16 backends with the key shape MobileDetect produces (40-char sha1 hex) before deploying.","Match on exception code, not message text — messages embed inner wording that can change between releases."],"tags":["cache","psr-16","mobile-detect","wrapper-exception","php"],"backgroundTag":"cache-backend-error","analyzedSha":"6ab7b0404df1da8da2aa2c56634362842d9c2a23","analyzedAt":"2026-08-21T04:49:48.090Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}