diff --git a/src/solver.c b/src/solver.c
index 0776cc048ae17f69d4f2d51a070354ef93f1998e..2318d7257f1b0b31aafe62a77e81ea04fced7175 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -218,9 +218,12 @@ static void discover_name(struct apk_solver_state *ss, struct apk_name *name)
 		pkg->ss.pinning_preferred = APK_DEFAULT_PINNING_MASK;
 		pkg->ss.pkg_available =
 			(pkg->filename != NULL) ||
-			(pkg->installed_size == 0) ||
-			(pkg->repos & db->available_repos);
-		pkg->ss.pkg_selectable = pkg->ss.pkg_available || pkg->ipkg;
+			(pkg->repos & db->available_repos & ~BIT(APK_REPOSITORY_CACHED));
+		/* Package is in 'cached' repository if filename is provided,
+		 * or it's a 'virtual' package with install_size zero */
+		pkg->ss.pkg_selectable =
+			(pkg->repos & db->available_repos) ||
+			pkg->ipkg;
 
 		repos = get_pkg_repos(db, pkg);
 		pkg->ss.tag_preferred =
@@ -497,10 +500,14 @@ static int compare_providers(struct apk_solver_state *ss,
 			return r;
 
 		/* Prefer available */
-		if (solver_flags & (APK_SOLVERF_AVAILABLE | APK_SOLVERF_REINSTALL)) {
+		if (solver_flags & APK_SOLVERF_AVAILABLE) {
 			r = (int)pkgA->ss.pkg_available - (int)pkgB->ss.pkg_available;
 			if (r)
 				return r;
+		} else if (solver_flags & APK_SOLVERF_REINSTALL) {
+			r = (int)pkgA->ss.pkg_selectable - (int)pkgB->ss.pkg_selectable;
+			if (r)
+				return r;
 		}
 	} else {
 		/* Prefer without errors */
@@ -529,10 +536,14 @@ static int compare_providers(struct apk_solver_state *ss,
 			return r;
 
 		/* Prefer available */
-		if (solver_flags & (APK_SOLVERF_AVAILABLE | APK_SOLVERF_REINSTALL)) {
+		if (solver_flags & APK_SOLVERF_AVAILABLE) {
 			r = (int)pkgA->ss.pkg_available - (int)pkgB->ss.pkg_available;
 			if (r)
 				return r;
+		} else if (solver_flags & APK_SOLVERF_REINSTALL) {
+			r = (int)pkgA->ss.pkg_selectable - (int)pkgB->ss.pkg_selectable;
+			if (r)
+				return r;
 		}
 
 		/* Prefer preferred pinning */