diff --git a/lib/private/Repair.php b/lib/private/Repair.php
index bb2967d7e6e2a6b208cf15ec780427b945bfc6fc..1fd204fcd845b6f5f20a05ec5c0e40c1af04c66b 100644
--- a/lib/private/Repair.php
+++ b/lib/private/Repair.php
@@ -127,7 +127,7 @@ class Repair implements IOutput{
 			new RepairLegacyStorages(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
 			new AssetCache(),
 			new FillETags(\OC::$server->getDatabaseConnection()),
-			new CleanTags(\OC::$server->getDatabaseConnection()),
+			new CleanTags(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager()),
 			new DropOldTables(\OC::$server->getDatabaseConnection()),
 			new DropOldJobs(\OC::$server->getJobList()),
 			new RemoveGetETagEntries(\OC::$server->getDatabaseConnection()),
diff --git a/lib/private/Repair/CleanTags.php b/lib/private/Repair/CleanTags.php
index 60ddeff08f362892eaa96d3ea808e1af36750854..4241fa6da3aa6c7c60233aacfddb292e2693740a 100644
--- a/lib/private/Repair/CleanTags.php
+++ b/lib/private/Repair/CleanTags.php
@@ -25,6 +25,7 @@ namespace OC\Repair;
 
 use OCP\DB\QueryBuilder\IQueryBuilder;
 use OCP\IDBConnection;
+use OCP\IUserManager;
 use OCP\Migration\IOutput;
 use OCP\Migration\IRepairStep;
 
@@ -38,11 +39,18 @@ class CleanTags implements IRepairStep {
 	/** @var IDBConnection */
 	protected $connection;
 
+	/** @var IUserManager */
+	protected $userManager;
+
+	protected $deletedTags = 0;
+
 	/**
 	 * @param IDBConnection $connection
+	 * @param IUserManager $userManager
 	 */
-	public function __construct(IDBConnection $connection) {
+	public function __construct(IDBConnection $connection, IUserManager $userManager) {
 		$this->connection = $connection;
+		$this->userManager = $userManager;
 	}
 
 	/**
@@ -56,11 +64,58 @@ class CleanTags implements IRepairStep {
 	 * Updates the configuration after running an update
 	 */
 	public function run(IOutput $output) {
+		$this->deleteOrphanTags($output);
 		$this->deleteOrphanFileEntries($output);
 		$this->deleteOrphanTagEntries($output);
 		$this->deleteOrphanCategoryEntries($output);
 	}
 
+	/**
+	 * Delete tags for deleted users
+	 */
+	protected function deleteOrphanTags(IOutput $output) {
+		$offset = 0;
+		while ($this->checkTags($offset)) {
+			$offset += 50;
+		}
+
+		$output->info(sprintf('%d tags of deleted users have been removed.', $this->deletedTags));
+	}
+
+	protected function checkTags($offset) {
+		$query = $this->connection->getQueryBuilder();
+		$query->select('uid')
+			->from('vcategory')
+			->groupBy('uid')
+			->orderBy('uid')
+			->setMaxResults(50)
+			->setFirstResult($offset);
+		$result = $query->execute();
+
+		$users = [];
+		$hadResults = false;
+		while ($row = $result->fetch()) {
+			$hadResults = true;
+			if (!$this->userManager->userExists($row['uid'])) {
+				$users[] = $row['uid'];
+			}
+		}
+		$result->closeCursor();
+
+		if (!$hadResults) {
+			// No more tags, stop looping
+			return false;
+		}
+
+		if (!empty($users)) {
+			$query = $this->connection->getQueryBuilder();
+			$query->delete('vcategory')
+				->where($query->expr()->in('uid', $query->createNamedParameter($users, IQueryBuilder::PARAM_STR_ARRAY)));
+			$this->deletedTags += $query->execute();
+		}
+		return true;
+	}
+
 	/**
 	 * Delete tag entries for deleted files
 	 */
diff --git a/tests/lib/Repair/CleanTagsTest.php b/tests/lib/Repair/CleanTagsTest.php
index 804fa4f66c9318dad1ba34ccbe76e999a487a28e..ac79907c52588cb6c4d5877799a2bd86c454d818 100644
--- a/tests/lib/Repair/CleanTagsTest.php
+++ b/tests/lib/Repair/CleanTagsTest.php
@@ -25,6 +25,9 @@ class CleanTagsTest extends \Test\TestCase {
 	/** @var \OCP\IDBConnection */
 	protected $connection;
 
+	/** @var \OCP\IUserManager|\PHPUnit_Framework_MockObject_MockObject */
+	protected $userManager;
+
 	/** @var int */
 	protected $createdFile;
 
@@ -38,8 +41,12 @@ class CleanTagsTest extends \Test\TestCase {
 			->disableOriginalConstructor()
 			->getMock();
 
+		$this->userManager = $this->getMockBuilder('\OCP\IUserManager')
+			->disableOriginalConstructor()
+			->getMock();
+
 		$this->connection = \OC::$server->getDatabaseConnection();
-		$this->repair = new \OC\Repair\CleanTags($this->connection);
+		$this->repair = new \OC\Repair\CleanTags($this->connection, $this->userManager);
 		$this->cleanUpTables();
 	}
 
@@ -86,6 +93,20 @@ class CleanTagsTest extends \Test\TestCase {
 		self::invokePrivate($this->repair, 'deleteOrphanCategoryEntries', [$this->outputMock]);
 		$this->assertEntryCount('vcategory_to_object', 2, 'Assert tag entries count after cleaning category entries');
 		$this->assertEntryCount('vcategory', 2, 'Assert tag categories count after cleaning category entries');
+
+
+		$this->addTagCategory('TestRepairCleanTags', 'contacts', 'userExists'); // Retained
+		$this->assertEntryCount('vcategory', 3, 'Assert tag categories count before cleaning categories by users');
+
+		$this->userManager->expects($this->exactly(2))
+			->method('userExists')
+			->willReturnMap([
+				['userExists', true],
+				['TestRepairCleanTags', false],
+			]);
+
+		self::invokePrivate($this->repair, 'deleteOrphanTags', [$this->outputMock]);
+		$this->assertEntryCount('vcategory', 1, 'Assert tag categories count after cleaning categories by users');
 	}
 
 	/**
@@ -107,13 +128,14 @@ class CleanTagsTest extends \Test\TestCase {
 	 *
 	 * @param string $category
 	 * @param string $type
+	 * @param string $user
 	 * @return int
 	 */
-	protected function addTagCategory($category, $type) {
+	protected function addTagCategory($category, $type, $user = 'TestRepairCleanTags') {
 		$qb = $this->connection->getQueryBuilder();
 		$qb->insert('vcategory')
 			->values([
-				'uid'		=> $qb->createNamedParameter('TestRepairCleanTags'),
+				'uid'		=> $qb->createNamedParameter($user),
 				'category'	=> $qb->createNamedParameter($category),
 				'type'		=> $qb->createNamedParameter($type),
 			])