diff --git a/compiler/GHC/Iface/Errors/Ppr.hs b/compiler/GHC/Iface/Errors/Ppr.hs
index 6d3cc42b2099ffaaf1af882bd7e459a8d1fc1c05..79fe58519a5eaa22704094bf5ae5acefb82bcd6c 100644
--- a/compiler/GHC/Iface/Errors/Ppr.hs
+++ b/compiler/GHC/Iface/Errors/Ppr.hs
@@ -279,9 +279,10 @@ cantFindErrorX pkg_hidden_hint may_show_locations mod_or_interface (CantFindInst
     mod_hidden pkg =
         text "it is a hidden module in the package" <+> quotes (ppr pkg)
 
-    unusable (pkg, reason)
-      = text "It is a member of the package"
-      <+> quotes (ppr pkg)
+    unusable (UnusableUnit unit reason reexport)
+      = text "It is " <> (if reexport then text "reexported from the package"
+                                      else text "a member of the package")
+      <+> quotes (ppr unit)
       $$ pprReason (text "which is") reason
 
 
diff --git a/compiler/GHC/Iface/Errors/Types.hs b/compiler/GHC/Iface/Errors/Types.hs
index 9bdac84a3a34510a88ed89a00cb639ce93bef33f..974fc1a5ec306b93a53b4c2220d8ad9ec65d4e4a 100644
--- a/compiler/GHC/Iface/Errors/Types.hs
+++ b/compiler/GHC/Iface/Errors/Types.hs
@@ -25,7 +25,7 @@ import GHC.Prelude
 import GHC.Types.Name (Name)
 import GHC.Types.TyThing (TyThing)
 import GHC.Unit.Types (Module, InstalledModule, UnitId, Unit)
-import GHC.Unit.State (UnitState, ModuleSuggestion, ModuleOrigin, UnusableUnitReason, UnitInfo)
+import GHC.Unit.State (UnitState, ModuleSuggestion, ModuleOrigin, UnusableUnit, UnitInfo)
 import GHC.Exception.Type (SomeException)
 import GHC.Unit.Types ( IsBootInterface )
 import Language.Haskell.Syntax.Module.Name ( ModuleName )
@@ -80,7 +80,7 @@ data CantFindInstalledReason
   | CouldntFindInFiles [FilePath]
   | GenericMissing
       [(Unit, Maybe UnitInfo)] [Unit]
-      [(Unit, UnusableUnitReason)] [FilePath]
+      [UnusableUnit] [FilePath]
   | MultiplePackages [(Module, ModuleOrigin)]
   deriving Generic
 
diff --git a/compiler/GHC/Unit/Finder.hs b/compiler/GHC/Unit/Finder.hs
index 25d3f68d002d39e7293bd95dae67896409becd5a..c113e2592f92af8e0b3c770278c8152776b9a193 100644
--- a/compiler/GHC/Unit/Finder.hs
+++ b/compiler/GHC/Unit/Finder.hs
@@ -301,7 +301,7 @@ findLookupResult fc fopts r = case r of
                        , fr_suggestions = [] })
      LookupUnusable unusable ->
        let unusables' = map get_unusable unusable
-           get_unusable (m, ModUnusable r) = (moduleUnit m, r)
+           get_unusable (_, ModUnusable r) = r
            get_unusable (_, r)             =
              pprPanic "findLookupResult: unexpected origin" (ppr r)
        in return (NotFound{ fr_paths = [], fr_pkg = Nothing
diff --git a/compiler/GHC/Unit/Finder/Types.hs b/compiler/GHC/Unit/Finder/Types.hs
index d3dad77eda672b8ae10ccd2fd1467510932e2f6f..fceb4b03648c70e1297ab80583ee331522c555c0 100644
--- a/compiler/GHC/Unit/Finder/Types.hs
+++ b/compiler/GHC/Unit/Finder/Types.hs
@@ -61,7 +61,7 @@ data FindResult
                                            --   but the *unit* is hidden
 
         -- | Module is in these units, but it is unusable
-      , fr_unusables   :: [(Unit, UnusableUnitReason)]
+      , fr_unusables   :: [UnusableUnit]
 
       , fr_suggestions :: [ModuleSuggestion] -- ^ Possible mis-spelled modules
       }
diff --git a/compiler/GHC/Unit/State.hs b/compiler/GHC/Unit/State.hs
index 0d406d407c887fc48e59e2582b06daa6f08029a3..aa16d401a0808ef5f7a39a586d844fb1a6216303 100644
--- a/compiler/GHC/Unit/State.hs
+++ b/compiler/GHC/Unit/State.hs
@@ -43,6 +43,7 @@ module GHC.Unit.State (
         LookupResult(..),
         ModuleSuggestion(..),
         ModuleOrigin(..),
+        UnusableUnit(..),
         UnusableUnitReason(..),
         pprReason,
 
@@ -173,8 +174,10 @@ data ModuleOrigin =
     -- (But maybe the user didn't realize), so we'll still keep track
     -- of these modules.)
     ModHidden
-    -- | Module is unavailable because the package is unusable.
-  | ModUnusable UnusableUnitReason
+
+    -- | Module is unavailable because the unit is unusable.
+  | ModUnusable !UnusableUnit
+
     -- | Module is public, and could have come from some places.
   | ModOrigin {
         -- | @Just False@ means that this module is in
@@ -192,6 +195,13 @@ data ModuleOrigin =
       , fromPackageFlag :: Bool
       }
 
+-- | A unusable unit module origin
+data UnusableUnit = UnusableUnit
+  { uuUnit        :: !Unit               -- ^ Unusable unit
+  , uuReason      :: !UnusableUnitReason -- ^ Reason
+  , uuIsReexport  :: !Bool               -- ^ Is the "module" a reexport?
+  }
+
 instance Outputable ModuleOrigin where
     ppr ModHidden = text "hidden module"
     ppr (ModUnusable _) = text "unusable module"
@@ -236,7 +246,8 @@ instance Semigroup ModuleOrigin where
                     text "x: " <> ppr x $$ text "y: " <> ppr y
             g Nothing x = x
             g x Nothing = x
-    x <> y = pprPanic "ModOrigin: hidden module redefined" $
+
+    x <> y = pprPanic "ModOrigin: module origin mismatch" $
                  text "x: " <> ppr x $$ text "y: " <> ppr y
 
 instance Monoid ModuleOrigin where
@@ -1818,21 +1829,36 @@ mkUnusableModuleNameProvidersMap :: UnusableUnits -> ModuleNameProvidersMap
 mkUnusableModuleNameProvidersMap unusables =
     nonDetFoldUniqMap extend_modmap emptyUniqMap unusables
  where
-    extend_modmap (_uid, (pkg, reason)) modmap = addListTo modmap bindings
+    extend_modmap (_uid, (unit_info, reason)) modmap = addListTo modmap bindings
       where bindings :: [(ModuleName, UniqMap Module ModuleOrigin)]
             bindings = exposed ++ hidden
 
-            origin = ModUnusable reason
-            pkg_id = mkUnit pkg
+            origin_reexport =  ModUnusable (UnusableUnit unit reason True)
+            origin_normal   =  ModUnusable (UnusableUnit unit reason False)
+            unit = mkUnit unit_info
 
             exposed = map get_exposed exposed_mods
-            hidden = [(m, mkModMap pkg_id m origin) | m <- hidden_mods]
-
-            get_exposed (mod, Just mod') = (mod, unitUniqMap mod' origin)
-            get_exposed (mod, _)         = (mod, mkModMap pkg_id mod origin)
-
-            exposed_mods = unitExposedModules pkg
-            hidden_mods  = unitHiddenModules pkg
+            hidden = [(m, mkModMap unit m origin_normal) | m <- hidden_mods]
+
+            -- with re-exports, c:Foo can be reexported from two (or more)
+            -- unusable packages:
+            --  Foo -> a:Foo (unusable reason A) -> c:Foo
+            --      -> b:Foo (unusable reason B) -> c:Foo
+            --
+            -- We must be careful to not record the following (#21097):
+            --  Foo -> c:Foo (unusable reason A)
+            --      -> c:Foo (unusable reason B)
+            -- But:
+            --  Foo -> a:Foo (unusable reason A)
+            --      -> b:Foo (unusable reason B)
+            --
+            get_exposed (mod, Just _) = (mod, mkModMap unit mod origin_reexport)
+            get_exposed (mod, _) = (mod, mkModMap unit mod origin_normal)
+              -- in the reexport case, we create a virtual module that doesn't
+              -- exist but we don't care as it's only used as a key in the map.
+
+            exposed_mods = unitExposedModules unit_info
+            hidden_mods  = unitHiddenModules  unit_info
 
 -- | Add a list of key/value pairs to a nested map.
 --
diff --git a/testsuite/tests/driver/T21097/Makefile b/testsuite/tests/driver/T21097/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..b90dcdb3ceabf89ecc376cd088d44dc58d073de5
--- /dev/null
+++ b/testsuite/tests/driver/T21097/Makefile
@@ -0,0 +1,7 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+T21097:
+	'$(GHC_PKG)' recache --package-db pkgdb
+	- '$(TEST_HC)' -package-db pkgdb -v0 Test.hs; test $$? -eq 2
diff --git a/testsuite/tests/driver/T21097/T21097.stderr b/testsuite/tests/driver/T21097/T21097.stderr
new file mode 100644
index 0000000000000000000000000000000000000000..565589c38c3b6b1a032ef03604a25d66e6026892
--- /dev/null
+++ b/testsuite/tests/driver/T21097/T21097.stderr
@@ -0,0 +1,16 @@
+
+Test.hs:3:1: error: [GHC-87110]
+    Could not load module ‘Foo’.
+    It is a member of the package ‘c-0.1’
+    which is unusable due to missing dependencies:
+      d-0.1
+    It is reexported from the package ‘b-0.1’
+    which is unusable due to missing dependencies:
+      c-0.1
+    It is reexported from the package ‘a-0.1’
+    which is unusable due to missing dependencies:
+      c-0.1
+    Use -v to see a list of the files searched for.
+  |
+3 | import Foo
+  | ^^^^^^^^^^
diff --git a/testsuite/tests/driver/T21097/Test.hs b/testsuite/tests/driver/T21097/Test.hs
new file mode 100644
index 0000000000000000000000000000000000000000..3a3151eb70a8b543b8d41d1e5511c8a4228d6259
--- /dev/null
+++ b/testsuite/tests/driver/T21097/Test.hs
@@ -0,0 +1,3 @@
+module Main where
+
+import Foo
diff --git a/testsuite/tests/driver/T21097/all.T b/testsuite/tests/driver/T21097/all.T
new file mode 100644
index 0000000000000000000000000000000000000000..5b4e4d479000d38bc29095d0ede10fe2727278a8
--- /dev/null
+++ b/testsuite/tests/driver/T21097/all.T
@@ -0,0 +1,4 @@
+# Package a and b both depend on c which is broken (depends on non-existing d)
+test('T21097',
+  [ extra_files(["pkgdb", "pkgdb/a.conf", "pkgdb/b.conf", "pkgdb/c.conf", "Test.hs"])
+  ], makefile_test, [])
diff --git a/testsuite/tests/driver/T21097/pkgdb/a.conf b/testsuite/tests/driver/T21097/pkgdb/a.conf
new file mode 100644
index 0000000000000000000000000000000000000000..108cbe35430a1853e1a16ddb2c8706d5fdbe8291
--- /dev/null
+++ b/testsuite/tests/driver/T21097/pkgdb/a.conf
@@ -0,0 +1,12 @@
+name:                 a
+version:              0.1
+visibility:           public
+id:                   a-0.1
+key:                  a-0.1
+abi:                  4e313a9f18a8df7d71cc2283205935c4
+exposed:              True
+
+exposed-modules:
+  Foo from c-0.1:Foo
+
+depends: c-0.1
diff --git a/testsuite/tests/driver/T21097/pkgdb/b.conf b/testsuite/tests/driver/T21097/pkgdb/b.conf
new file mode 100644
index 0000000000000000000000000000000000000000..abffed2fc18783b5e0aea991fc24a9f0cd01e705
--- /dev/null
+++ b/testsuite/tests/driver/T21097/pkgdb/b.conf
@@ -0,0 +1,12 @@
+name:                 b
+version:              0.1
+visibility:           public
+id:                   b-0.1
+key:                  b-0.1
+abi:                  4e313a9f18a8df7d71cc2283205935c4
+exposed:              True
+
+exposed-modules:
+  Foo from c-0.1:Foo
+
+depends:              c-0.1
diff --git a/testsuite/tests/driver/T21097/pkgdb/c.conf b/testsuite/tests/driver/T21097/pkgdb/c.conf
new file mode 100644
index 0000000000000000000000000000000000000000..b183748777e5c5baa41f1a360ef696aea05550d2
--- /dev/null
+++ b/testsuite/tests/driver/T21097/pkgdb/c.conf
@@ -0,0 +1,12 @@
+name:                 c
+version:              0.1
+visibility:           public
+id:                   c-0.1
+key:                  c-0.1
+abi:                  4e313a9f18a8df7d71cc2283205935c4
+exposed:              True
+
+exposed-modules:
+  Foo
+
+depends: d-0.1
diff --git a/testsuite/tests/driver/T21097b/Makefile b/testsuite/tests/driver/T21097b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..6455817a300f2c8188e14e897bbb4feda141bf36
--- /dev/null
+++ b/testsuite/tests/driver/T21097b/Makefile
@@ -0,0 +1,7 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+T21097b:
+	'$(GHC_PKG)' recache --package-db pkgdb
+	'$(TEST_HC)' -no-global-package-db -no-user-package-db -package-db pkgdb -v0 Test.hs -ddump-mod-map
diff --git a/testsuite/tests/driver/T21097b/T21097b.stdout b/testsuite/tests/driver/T21097b/T21097b.stdout
new file mode 100644
index 0000000000000000000000000000000000000000..e0380edd6c4009a9cd641755524dbc516e387966
--- /dev/null
+++ b/testsuite/tests/driver/T21097b/T21097b.stdout
@@ -0,0 +1,5 @@
+
+==================== Module Map ====================
+Foo                                               a-0.1 (exposed package)
+
+
diff --git a/testsuite/tests/driver/T21097b/Test.hs b/testsuite/tests/driver/T21097b/Test.hs
new file mode 100644
index 0000000000000000000000000000000000000000..3a3151eb70a8b543b8d41d1e5511c8a4228d6259
--- /dev/null
+++ b/testsuite/tests/driver/T21097b/Test.hs
@@ -0,0 +1,3 @@
+module Main where
+
+import Foo
diff --git a/testsuite/tests/driver/T21097b/all.T b/testsuite/tests/driver/T21097b/all.T
new file mode 100644
index 0000000000000000000000000000000000000000..ee47c0610ee28eb982664482e60fa21829874b54
--- /dev/null
+++ b/testsuite/tests/driver/T21097b/all.T
@@ -0,0 +1,6 @@
+# Package b is unusable (broken dependency) and reexport Foo from a (which is usable)
+test('T21097b',
+  [ extra_files(["pkgdb", "pkgdb/a.conf", "pkgdb/b.conf", "Test.hs"])
+  , ignore_stderr
+  , exit_code(2)
+  ], makefile_test, [])
diff --git a/testsuite/tests/driver/T21097b/pkgdb/a.conf b/testsuite/tests/driver/T21097b/pkgdb/a.conf
new file mode 100644
index 0000000000000000000000000000000000000000..b76d54fc287647946c374a376394e44b84c35099
--- /dev/null
+++ b/testsuite/tests/driver/T21097b/pkgdb/a.conf
@@ -0,0 +1,10 @@
+name:                 a
+version:              0.1
+visibility:           public
+id:                   a-0.1
+key:                  a-0.1
+abi:                  4e313a9f18a8df7d71cc2283205935c4
+exposed:              True
+
+exposed-modules:
+  Foo
diff --git a/testsuite/tests/driver/T21097b/pkgdb/b.conf b/testsuite/tests/driver/T21097b/pkgdb/b.conf
new file mode 100644
index 0000000000000000000000000000000000000000..264b05bea2b52d7c51e661a93cde283d4f7c2704
--- /dev/null
+++ b/testsuite/tests/driver/T21097b/pkgdb/b.conf
@@ -0,0 +1,12 @@
+name:                 b
+version:              0.1
+visibility:           public
+id:                   b-0.1
+key:                  b-0.1
+abi:                  4e313a9f18a8df7d71cc2283205935c4
+exposed:              True
+
+exposed-modules:
+  Foo from a-0.1:Foo
+
+depends: a-0.1, missing-0.1
diff --git a/testsuite/tests/driver/T21097b/pkgdb/c.conf b/testsuite/tests/driver/T21097b/pkgdb/c.conf
new file mode 100644
index 0000000000000000000000000000000000000000..b183748777e5c5baa41f1a360ef696aea05550d2
--- /dev/null
+++ b/testsuite/tests/driver/T21097b/pkgdb/c.conf
@@ -0,0 +1,12 @@
+name:                 c
+version:              0.1
+visibility:           public
+id:                   c-0.1
+key:                  c-0.1
+abi:                  4e313a9f18a8df7d71cc2283205935c4
+exposed:              True
+
+exposed-modules:
+  Foo
+
+depends: d-0.1