dune .mli / .ml signature mismatch (unbound in signature) in CI
When an .mli mentions a type or value the .ml does not (or no longer) defines, the module cannot be sealed against its interface. CI fails deterministically wherever the two files disagree.
What this error means
dune build fails with "Error: Unbound type constructor X" or "The value X is required but not provided" pointing at the .mli, after the implementation changed.
File "lib/api.mli", line 4, characters 15-20:
4 | val fetch : query -> result
^^^^^
Error: Unbound type constructor queryCommon causes
The interface references a removed type or value
The .mli still names something the .ml deleted or renamed, so the signature cannot be satisfied.
A type moved without updating the interface
A type definition moved to another module but the .mli still expects it locally.
How to fix it
Sync the interface to the implementation
- Read which type or value the
.mlireferences that is missing. - Restore or re-expose it in the
.ml, or remove it from the.mli. - Rebuild to confirm the interface seals.
(* re-add the type the mli expects, or drop the val from the mli *)
type query = { q : string }Regenerate the interface as a baseline
Let dune print the inferred signature so you can compare it against the committed .mli.
dune build @check
ocaml-print-intf lib/api.mlHow to prevent it
- Change
.mliand.mlin the same commit for public edits. - Keep types the interface exposes defined in the same module.
- Build the check alias locally before pushing.