{"record":{"id":"573f51e7495a4325","repo":"doctrine/cache","slug":"expected-time-to-be-either-an-integer-an-instance-of-573f51","errorCode":null,"errorMessage":"Expected $time to be either an integer, an instance of DateInterval or null, got %s","messagePattern":"Expected \\$time to be either an integer, an instance of DateInterval or null, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/Doctrine/Common/Cache/Psr6/TypedCacheItem.php","lineNumber":83,"sourceCode":"            ));\n        }\n\n        return $this;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function expiresAfter($time): static\n    {\n        if ($time === null) {\n            $this->expiry = null;\n        } elseif ($time instanceof DateInterval) {\n            $this->expiry = microtime(true) + DateTime::createFromFormat('U', 0)->add($time)->format('U.u');\n        } elseif (is_int($time)) {\n            $this->expiry = $time + microtime(true);\n        } else {\n            throw new TypeError(sprintf(\n                'Expected $time to be either an integer, an instance of DateInterval or null, got %s',\n                get_debug_type($time)\n            ));\n        }\n\n        return $this;\n    }\n\n    /**\n     * @internal\n     */\n    public function getExpiry(): ?float\n    {\n        return $this->expiry;\n    }\n}\n","sourceCodeStart":65,"sourceCodeEnd":100,"githubUrl":"https://github.com/doctrine/cache/blob/e0a9919443c1e918251c23b65eddd9a66fafacb3/lib/Doctrine/Common/Cache/Psr6/TypedCacheItem.php#L65-L100","documentation":"TypedCacheItem::expiresAfter() accepts null, int seconds, or DateInterval; anything else raises a TypeError with the debug type embedded via get_debug_type(). This mirrors CacheItem::expiresAfter but in the typed item class.","triggerScenarios":"Calling expiresAfter() with a string TTL from config/env, a float, or a DateTime object instead of the accepted types.","commonSituations":"TTL values sourced from .env or JSON as strings; refactors moving from untyped to typed cache items; passing DateInterval where int was expected is fine, but strings are not auto-parsed.","solutions":["Cast to int: expiresAfter((int) $ttl)","Convert interval strings with new DateInterval($spec)","Use expiresAt() with DateTimeImmutable for absolute expiry"],"exampleFix":"// before\n$item->expiresAfter(getenv('CACHE_TTL')); // string\n// after\n$item->expiresAfter((int) getenv('CACHE_TTL'));","handlingStrategy":"type-guard","validationCode":"if ($time !== null && !is_int($time) && !$time instanceof \\DateInterval) { throw new InvalidArgumentException('time must be int, DateInterval or null'); }","typeGuard":"function acceptsTtl(mixed $v): bool { return $v === null || is_int($v) || $v instanceof \\DateInterval; }","tryCatchPattern":"try { $item->expiresAfter($ttl); } catch (\\TypeError $e) { /* coerce or report */ }","preventionTips":["Cast env/config TTLs to int at config load","Use DateInterval for interval strings","Keep absolute and relative expiry APIs distinct in your code"],"tags":["php","psr6","cache","typeerror","ttl"],"backgroundTag":"type-mismatch","analyzedSha":"e0a9919443c1e918251c23b65eddd9a66fafacb3","analyzedAt":"2026-09-13T19:23:46.714Z","contentChangedAt":"2026-09-13T19:23:46.714Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}