diff --git a/src/dune_rules/ml_sources.ml b/src/dune_rules/ml_sources.ml
index eedb18e6218f..eb8cc184e498 100644
--- a/src/dune_rules/ml_sources.ml
+++ b/src/dune_rules/ml_sources.ml
@@ -465,25 +465,33 @@ let modules_of_stanzas =
       | true ->
         (match Stanza.repr stanza with
          | Library.T lib ->
-           (* jeremiedimino: this [Resolve.get] means that if the user writes an
-              invalid [implements] field, we will get an error immediately even if
-              the library is not built. We should change this to carry the
-              [Or_exn.t] a bit longer. *)
-           let+ sources, modules =
-             let lookup_vlib = lookup_vlib ~loc:lib.buildable.loc in
-             make_lib_modules
-               ~expander
-               ~dir
-               ~libs
-               ~lookup_vlib
-               ~modules
-               ~lib
-               ~include_subdirs
-               ~version:lib.dune_version
-             >>= Resolve.read_memo
+           let* available =
+             let* db = libs in
+             let src_dir = Path.drop_optional_build_context_src_exn (Path.build dir) in
+             Lib.DB.available_by_lib_id db (Local (Library.to_lib_id ~src_dir lib))
            in
-           let obj_dir = Library.obj_dir lib ~dir in
-           `Library { Modules.stanza = lib; sources; modules; dir; obj_dir }
+           if not available
+           then Memo.return `Skip
+           else
+             (* jeremiedimino: this [Resolve.get] means that if the user writes an
+                invalid [implements] field, we will get an error immediately even if
+                the library is not built. We should change this to carry the
+                [Or_exn.t] a bit longer. *)
+             let+ sources, modules =
+               let lookup_vlib = lookup_vlib ~loc:lib.buildable.loc in
+               make_lib_modules
+                 ~expander
+                 ~dir
+                 ~libs
+                 ~lookup_vlib
+                 ~modules
+                 ~lib
+                 ~include_subdirs
+                 ~version:lib.dune_version
+               >>= Resolve.read_memo
+             in
+             let obj_dir = Library.obj_dir lib ~dir in
+             `Library { Modules.stanza = lib; sources; modules; dir; obj_dir }
          | Executables.T exes -> make_executables ~dir ~expander ~modules ~project exes
          | Tests.T { exes; _ } -> make_executables ~dir ~expander ~modules ~project exes
          | Melange_stanzas.Emit.T mel ->
diff --git a/test/blackbox-tests/test-cases/lib-collision/lib-collision-private-optional.t b/test/blackbox-tests/test-cases/lib-collision/lib-collision-private-optional.t
new file mode 100644
index 000000000000..b767969d8b35
--- /dev/null
+++ b/test/blackbox-tests/test-cases/lib-collision/lib-collision-private-optional.t
@@ -0,0 +1,46 @@
+Private libraries using the same library name, in the same context, defined in
+the same folder. One of them is unavailable because it's `(optional)` and a
+dependency is missing.
+
+  $ cat > dune-project << EOF
+  > (lang dune 3.13)
+  > EOF
+
+  $ cat > dune << EOF
+  > (library
+  >  (name foo)
+  >  (libraries xxx)
+  >  (optional))
+  > (library
+  >  (name foo))
+  > EOF
+  $ cat > foo.ml << EOF
+  > let x = "hello"
+  > EOF
+
+Without any consumers of the libraries
+
+  $ dune build
+
+With some consumer of the library
+
+  $ cat > dune << EOF
+  > (library
+  >  (name foo)
+  >  (modules foo)
+  >  (libraries xxx)
+  >  (optional))
+  > (library
+  >  (modules foo)
+  >  (name foo))
+  > (executable
+  >  (name main)
+  >  (modules main)
+  >  (libraries foo))
+  > EOF
+
+  $ cat > main.ml <<EOF
+  > let () = print_endline Foo.x
+  > EOF
+
+  $ dune build