serbanghita/Mobile-Detect · error · MobileDetectException

IS_MAGIC_ERR

IS_MAGIC_ERR

Error message

Cache problem in is(): {$e->getMessage()}

What it means

is() (src/MobileDetect.php:1548) re-throws any CacheException, CacheInvalidArgumentException, or Psr\SimpleCache\InvalidArgumentException raised during its cache get/set or during createCacheKey() as MobileDetectException with code IS_MAGIC_ERR (0x4), chaining the cause. Because every magic isXXXX() call routes through __call -> is(), this is the wrapper you hit when cache trouble occurs inside a magic detection call (e.g. isIphone(), isBot()).

Source

Thrown at src/MobileDetect.php:1548

        if ($this->isUserAgentEmpty()) {
            return false;
        }

        // Cache check.
        try {
            $cacheKey = $this->createCacheKey($ruleName);
            $cacheItem = $this->cache->get($cacheKey);
            if ($cacheItem !== null) {
                return $cacheItem;
            }

            $result = $this->matchUserAgentWithRule($ruleName);

            // Cache save.
            $this->cache->set($cacheKey, $result, $this->config['cacheTtl']);
            return $result;
        } catch (CacheInvalidArgumentException | CacheException | PsrInvalidArgumentException $e) {
            throw new MobileDetectException("Cache problem in is(): {$e->getMessage()}", MobileDetectExceptionCode::IS_MAGIC_ERR, $e);
        }
    }

    /**
     * Some detection rules are relative (not standard),
     * because of the diversity of devices, vendors and
     * their conventions in representing the User-Agent or
     * the HTTP headers.
     *
     * This method will be used to check custom regexes against
     * the User-Agent string.
     *
     * @param string $regex
     * @param string $userAgent
     * @return bool
     *
     * @todo: search in the HTTP headers too.
     */

View on GitHub (pinned to 6ab7b0404d)

Solutions

  1. Drill into the cause: $e->getPrevious() — 'cacheKeyFn is not a function.' means a config problem; 'Invalid key: ...' means the key fn output violates the charset rule.
  2. Restore a callable hash for 'cacheKeyFn' ('sha1' default, 'md5', or a hash() closure).
  3. Audit the custom CacheInterface implementation's exact get/set signatures and failure modes; have backend outages return defaults or log rather than throw when detection is non-critical.
  4. Catch narrowly by code (IS_MAGIC_ERR) so genuine detection bugs aren't swallowed.

Example fix

// before
if ($detect->isBot()) { /* ... */ } // Redis down -> IS_MAGIC_ERR wrapper

// after
use Detection\Exception\MobileDetectException;
use Detection\Exception\MobileDetectExceptionCode;

try {
    $bot = $detect->isBot();
} catch (MobileDetectException $e) {
    if ($e->getCode() !== MobileDetectExceptionCode::IS_MAGIC_ERR) {
        throw $e;
    }
    $bot = false; // cache degraded; log $e->getPrevious()->getMessage()
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Guard the two root causes before any magic call:
$config = ['cacheKeyFn' => 'sha1'];
assert(is_callable($config['cacheKeyFn']));
// and prove the backend round-trips one MobileDetect-shaped key:
$cache->set(str_repeat('a', 40), true, 1);

Type guard

// The bundled default never fails; guard only swapped-in backends:
function backendAcceptsDetectorKeys(\Psr\SimpleCache\CacheInterface $c): bool
{
    try {
        return $c->set(str_repeat('a', 40), 1, 1);
    } catch (\Throwable) {
        return false;
    }
}

Try / catch

catch (MobileDetectException $e) {
    if ($e->getCode() === MobileDetectExceptionCode::IS_MAGIC_ERR) {
        // is()/isXXXX() cache path failed; retry cache-less
        $fresh = new \Detection\MobileDetect();
        $fresh->setUserAgent($ua);
        $result = $fresh->is($rule);
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: $detect->isIphone() with 'cacheKeyFn' misconfigured (non-callable, or producing keys that fail checkKey) — the inner CacheException/CacheInvalidArgumentException originates in createCacheKey() or the Cache; a custom PSR-16 backend injected instead of the bundled Cache throwing on get/set (Redis down, strict key validation, unserializable values).

Common situations: Surfaces only after replacing the default in-memory cache with a real backend (default Cache + sha1 keys always pass validation); production-only cache outages; DI misconfiguration after a framework upgrade; per-user UA-flag caching with keys built outside MobileDetect.

Related errors


AI-assisted analysis of serbanghita/Mobile-Detect@6ab7b0404d (2026-08-21). Data as JSON: /api/errors/e7eb807823d0085d. Report an issue: GitHub.