lcobucci/jwt · error · Lcobucci\JWT\Token\InvalidTokenStructure

Value is not in the allowed date format

Error message

Value is not in the allowed date format: {value}

What it means

Date-related registered claims (iat, nbf, exp) must be numeric timestamps. When the parsed value is neither an int, float, nor numeric string, convertDate rejects it because it cannot be converted to a DateTimeImmutable. The library strictly enforces the timestamp-based date format for these claims.

Solutions

  1. Fix the issuer to emit integer Unix timestamps for iat/nbf/exp
  2. Convert the value to a Unix timestamp on the issuing side, e.g. $d->getTimestamp()
  3. Parse the token leniently or pre-transform the claims if you control the parsing pipeline

Example fix

// before
{"iat": "2026-01-01T00:00:00Z"}
// after
{"iat": 1767225600}
Defensive patterns

Strategy: validation

Validate before calling

$claims = json_decode(base64_decode($payloadPart), true);
foreach (['iat','nbf','exp'] as $c) {
    if (isset($claims[$c]) && !is_numeric($claims[$c])) {
        throw new \InvalidArgumentException("$c must be a numeric Unix timestamp");
    }
}

Type guard

function isNumericTimestamp(mixed $v): bool { return is_int($v) || is_float($v) || (is_string($v) && is_numeric($v)); }

Try / catch

try {
    $token = $parser->parse($jwt);
} catch (InvalidTokenStructure $e) {
    // token has a non-numeric date claim; reject
}

Prevention

When it happens

Trigger: Parsing a token whose iat/nbf/exp claim is a non-numeric value such as an ISO-8601 date string ("2026-01-01T00:00:00Z"), a bool, an array, or null instead of a Unix timestamp.

Common situations: Issuers that emit human-readable date strings instead of Unix timestamps (a common spec misunderstanding); tokens generated by libraries configured for ISO dates; manually edited token payloads.

Related errors


AI-assisted analysis of lcobucci/jwt@375813049c (2026-09-14). Data as JSON: /api/errors/3f94a5ceb680e436. Report an issue: GitHub.

Appendix: source

Thrown at src/Token/Parser.php:155

     * @param array<string, mixed> $array
     * @param non-empty-string     $part
     *
     * @phpstan-assert array<non-empty-string, mixed> $array
     */
    private function guardAgainstEmptyStringKeys(array $array, string $part): void
    {
        foreach ($array as $key => $value) {
            if ($key === '') {
                throw InvalidTokenStructure::arrayExpected($part);
            }
        }
    }

    /** @throws InvalidTokenStructure */
    private function convertDate(int|float|string $timestamp): DateTimeImmutable
    {
        if (! is_numeric($timestamp)) {
            throw InvalidTokenStructure::dateIsNotParseable($timestamp);
        }

        $normalizedTimestamp = number_format((float) $timestamp, self::MICROSECOND_PRECISION, '.', '');

        $date = DateTimeImmutable::createFromFormat('U.u', $normalizedTimestamp);

        if ($date === false) {
            throw InvalidTokenStructure::dateIsNotParseable($normalizedTimestamp);
        }

        return $date;
    }

    /**
     * Returns the signature from given data
     *
     * @param non-empty-string $data
     */

View on GitHub (pinned to 375813049c)