Specifying a virtual module that isn't inside the (modules ..) field: $ cat > dune-project << EOF > (lang dune 3.7) > EOF $ mkdir src $ cat > src/dune << EOF > (library > (name foo) > (wrapped false) > (virtual_modules x) > (modules y)) > EOF $ touch src/x.mli $ cat > src/y.ml << EOF > module type F = X > EOF $ mkdir src/impl $ cat > src/impl/dune << EOF > (library > (name impl) > (implements foo)) > EOF $ touch src/impl/x.ml X is warned about: $ dune build File "src/dune", line 4, characters 18-19: 4 | (virtual_modules x) ^ Warning: These modules appear in the virtual_modules field: - X They must also appear in the modules field. File "src/y.ml", line 1, characters 16-17: 1 | module type F = X ^ Error: Unbound module type X File "src/impl/dune", lines 1-3, characters 0-40: 1 | (library 2 | (name impl) 3 | (implements foo)) Error: No rule found for src/.foo.objs/y.impl.all-deps [1] In 3.11 onwards this warning becomes an error $ cat > dune-project << EOF > (lang dune 3.11) > EOF $ dune build ./bar.exe File "src/dune", line 4, characters 18-19: 4 | (virtual_modules x) ^ Error: These modules appear in the virtual_modules field: - X They must also appear in the modules field. [1] This should be ignored if we are in vendored_dirs $ cat > dune << EOF > (vendored_dirs src) > (executable > (name bar) > (libraries foo)) > EOF $ cat > bar.ml $ dune build ./bar.exe Error: No implementation found for virtual library "foo" in _build/default/src. -> required by executable bar in dune:3 -> required by _build/default/.bar.eobjs/native/dune__exe__Bar.cmx -> required by _build/default/bar.exe [1]