_get_go_module_dependencies() sends the module path through auto_module_mappings before it reads go.mod. DH_GOPKG and the use targets go through the same mapping. When the package being built declares a /vN module path, and an older version of itself is installed at the directory without the suffix, the mapping points the walk at the installed copy. The requirements of the sources being built are then never followed, and the modules they need end up neither replaced nor stubbed in go.work. The mapping is mine, from commit 1ff68b9 for bug 1149023. It was tested from the consumer side only, where the module being built and the mapped module are never the same. Reproducer, two native packages. Package one ships usr/share/gocode/src/example.debian.org/walkstub/go.mod with the line "module example.debian.org/walkstub/v2". Package two declares XS-Go-Import-Path: example.debian.org/walkstub/v2, has the same module line in its own go.mod, requires github.com/google/go-containerregistry v0.20.7, build depends on package one, and prints _build/go.work after dh_auto_configure. Both builds are sbuild runs in a clean sid chroot: package one installed Checking dependencies of go.work replace lines no 362 1548, auto/sdk stubbed yes 2 1495, auto/sdk missing With package one installed the log shows the shadowing twice: Checking dependencies of example.debian.org/walkstub/v2 ... installed at example.debian.org/walkstub In a real package the build stops. golang-github-theupdateframework-go-tuf, ported to dh-go with XS-Go-Import-Path github.com/theupdateframework/go-tuf/v2 while sid still ships the library at the path without the suffix, fails with github.com/google/go-containerregistry@v0.20.7 requires go.opentelemetry.io/auto/sdk@v1.1.0: module lookup disabled by GOPROXY=off for a module that is in neither its go.mod nor its debian/rules. A circular build dependency is what installs the old version, which is normal for a library that its own reverse dependency needs to run the tests. Please merge https://salsa.debian.org/go-team/dh-go/-/merge_requests/6 The patch only follows the mapping when the build directory does not already hold that module at its own path: --- a/lib/Debian/Debhelper/Buildsystem/golang.pm +++ b/lib/Debian/Debhelper/Buildsystem/golang.pm @@ - } elsif (exists $this->{auto_module_mappings}{$gomodule}) { + } elsif (exists $this->{auto_module_mappings}{$gomodule} + and not -e $this->get_buildpath("src/$gomodule/go.mod")) + { # A module can be installed at a path other than its module # path, e.g. github.com/foo/bar/v2 under github.com/foo/bar. # Its requirements must still be followed, otherwise they end # up neither replaced nor stubbed in go.work. + # + # Only follow the mapping when the build directory does not hold + # that module already. The sources of the package being built are + # copied to src/$DH_GOPKG, and an older version of the same module + # can be installed at another path. The mapping would then send the + # walk to the installed copy instead of the source being built. $gomodule = $this->{auto_module_mappings}{$gomodule}; verbose_print("... installed at $gomodule"); } I also rebuilt every source that build depends on dh-go, 27 of them, in a clean sid chroot with the patch in place. All 27 come back "Status: successful", the eight with a -vN-dev binary among them. I took go-sendxmpp from sid, 0.17.1-1, because the version in testing does not build against the dependencies in sid with 1.69 either. Verified with the same two packages: the shadowed build goes back to 362 dependency checks, 1548 replace lines and the stub. The case of bug 1149023 is unchanged, checked with a consumer package whose dependency is installed at the path without the suffix and whose requirements only the mapping can reach: the mapping is still followed and that requirement is still stubbed, with 1.69 and with the patch.