ramsey/uuid · error · UnsupportedOperationException

Not a time-based UUID

Error message

Not a time-based UUID

What it means

Uuid::fromString() returns a LazyUuidFromString that unwraps to the concrete UUID on demand. Its deprecated getTimestamp() asserts the fields implement Rfc4122FieldsInterface and then requires version 1; any other version (2, 3, 4, 5, 6, 7, 8, nil, max) throws UnsupportedOperationException because only Gregorian time-based UUIDs carry an RFC timestamp.

Source

Thrown at src/Lazy/LazyUuidFromString.php:394

        assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);

        return $instance->getNumberConverter()->fromHex($fields->getTimeMid()->toString());
    }

    /**
     * @deprecated Use {@see UuidInterface::getFields()} to get a {@see FieldsInterface} instance. If it is a
     *     {@see Rfc4122FieldsInterface} instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()} and use
     *     the arbitrary-precision math library of your choice to convert it to a string integer.
     */
    public function getTimestamp(): string
    {
        $instance = ($this->unwrapped ?? $this->unwrap());

        $fields = $instance->getFields();
        assert($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface);

        if ($fields->getVersion() !== 1) {
            throw new UnsupportedOperationException('Not a time-based UUID');
        }

        return $instance->getNumberConverter()->fromHex($fields->getTimestamp()->toString());
    }

    public function toUuidV1(): UuidV1
    {
        $instance = ($this->unwrapped ?? $this->unwrap());

        if ($instance instanceof UuidV1) {
            return $instance;
        }

        assert($instance instanceof UuidV6);

        return $instance->toUuidV1();
    }

View on GitHub (pinned to da5b521600)

Solutions

  1. Branch on version first: if ($uuid->getFields()->getVersion() === 1) { ... } before calling getTimestamp()
  2. Follow the deprecation: use $uuid->getFields() (Rfc4122FieldsInterface) and its getTimestamp() with your own math library
  3. If extracting time from v6/v7 UUIDs, use getDateTime() on those classes instead of getTimestamp()

Example fix

// before
$ts = \Ramsey\Uuid\Uuid::fromString($userInput)->getTimestamp();

// after
$uuid = \Ramsey\Uuid\Uuid::fromString($userInput);
$fields = $uuid->getFields();
if (!$fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface || $fields->getVersion() !== 1) {
    throw new InvalidArgumentException('Expected a time-based (v1) UUID');
}
$ts = $uuid->getTimestamp();
Defensive patterns

Strategy: validation

Validate before calling

$uuid = \Ramsey\Uuid\Uuid::fromString($input);
$fields = $uuid->getFields();
if ($fields instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface && $fields->getVersion() === 1) {
    $ts = $uuid->getTimestamp();
}

Type guard

function isTimeBasedV1(\Ramsey\Uuid\UuidInterface $uuid): bool
{
    $f = $uuid->getFields();
    return $f instanceof \Ramsey\Uuid\Rfc4122\FieldsInterface && $f->getVersion() === 1;
}

Try / catch

try {
    $ts = $uuid->getTimestamp();
} catch (\Ramsey\Uuid\Exception\UnsupportedOperationException $e) {
    // not a version 1 UUID; skip timestamp extraction
}

Prevention

When it happens

Trigger: Calling getTimestamp() on the result of Uuid::fromString() or on a UUID obtained from external input whose version is not 1 — e.g. Uuid::fromString('0f4b0fd0-0f4b-4ef0-9f3f-0242ac110002')->getTimestamp() (version 4). Note version 6/7 timestamps live on getDateTime()/fields instead.

Common situations: Log/DB parsing code that assumes all incoming UUIDs are v1 (e.g. legacy primary keys migrated to v4/v7); refactoring that feeds arbitrary UUID strings into timestamp extraction; version changes upstream in another service's ID generation.

Related errors


AI-assisted analysis of ramsey/uuid@da5b521600 (2026-08-21). Data as JSON: /api/errors/b28d68eeec8fb92d. Report an issue: GitHub.