ramsey/uuid · error · UnsupportedOperationException

The provided factory does not support the uuid8() method

Error message

The provided factory does not support the uuid8() method

What it means

Uuid::uuid8() delegates to the globally registered factory, but uuid8() is an optional capability beyond UuidFactoryInterface — the default Ramsey\Uuid\UuidFactory implements it (custom-format v8 UUIDs shipped with version 4.7 of the library). If the registered factory has no uuid8() method, the method_exists() check fails and Ramsey\Uuid\Exception\UnsupportedOperationException is thrown. This guards against custom or mock factories that predate or omit v8 support.

Source

Thrown at src/Uuid.php:725

     *
     * @return UuidInterface A UuidInterface instance that represents a version 8 UUID
     *
     * @pure
     */
    public static function uuid8(string $bytes): UuidInterface
    {
        /** @phpstan-ignore possiblyImpure.methodCall */
        $factory = self::getFactory();

        if (method_exists($factory, 'uuid8')) {
            /**
             * @var UuidInterface
             * @phpstan-ignore possiblyImpure.methodCall
             */
            return $factory->uuid8($bytes);
        }

        throw new UnsupportedOperationException('The provided factory does not support the uuid8() method');
    }
}

View on GitHub (pinned to da5b521600)

Solutions

  1. Extend Ramsey\Uuid\UuidFactory with the custom factory — uuid8() comes along for free
  2. Add uuid8(string $bytes): UuidInterface to the custom factory and delegate to an inner UuidFactory when wrapping one
  3. Refresh test mocks/doubles so they stub uuid8()
  4. Guard call sites: if (!method_exists(Uuid::getFactory(), 'uuid8')) construct via Uuid::fromBytes($bytes) with the v8 bits set manually

Example fix

// before: decorator factory forwards only interface methods
Uuid::setFactory(new TimingDecoratorFactory($innerFactory)); // no uuid8()
$uuid = Uuid::uuid8($bytes);
// UnsupportedOperationException: The provided factory does not support the uuid8() method

// after: extend UuidFactory (or forward the method) and keep v8 support
final class TimingDecoratorFactory extends UuidFactory
{
    public function uuid8(string $bytes): UuidInterface
    {
        return parent::uuid8($bytes);
    }
}
Uuid::setFactory(new TimingDecoratorFactory());
$uuid = Uuid::uuid8($bytes);
Defensive patterns

Strategy: type-guard

Validate before calling

// Run before calling Uuid::uuid8()
if (!method_exists(Uuid::getFactory(), 'uuid8')) {
    throw new \RuntimeException('Registered UUID factory does not support uuid8()');
}

Type guard

use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidFactory;

function factorySupportsUuid8(): bool
{
    return Uuid::getFactory() instanceof UuidFactory
        || method_exists(Uuid::getFactory(), 'uuid8');
}

Try / catch

use Ramsey\Uuid\Exception\UnsupportedOperationException;

try {
    $uuid = Uuid::uuid8($bytes);
} catch (UnsupportedOperationException $e) {
    // custom-layout path unavailable on this factory
    throw new \RuntimeException('Enable a factory with uuid8() support', 0, $e);
}

Prevention

When it happens

Trigger: Calling Uuid::setFactory($factory) with a factory implementing only UuidFactoryInterface, a decorator that does not forward uuid8(), or a PHPUnit mock without the method — then calling Uuid::uuid8($bytes) with the 16-byte custom blob.

Common situations: Introducing v8 custom-format UUIDs in apps with an existing custom factory; mocks/doubles built before the method existed; wrapper factories in DI containers forwarding only the interface methods; library upgrades where bindings still construct old wrappers.

Related errors


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