protected function validate($value, $constraints, ?string $propertyPath = null): void
    {
        try {
            $violations = $this->validator->validate($value, $constraints);
        } catch (Throwable $t) {
            throw ValidationException::validationFailed($propertyPath ?? '', $t->getMessage(), $t);
        }

        if (count($violations) === 0) {
            return;
        }

        $propertyName = $violations[0]->getPropertyPath() ?? '';
        if ($propertyName === '') {
            $propertyName = $propertyPath ?? '';
        }

        throw ValidationException::validationFailed($propertyName, $violations[0]->getMessage());
    }