== Detecting missing or bad Go modules and module versions I recently wrote about [[the case of a half-missing Go import GoHalfMissingImport]], where a particular version of a module had been removed upstream but was still available through [[the (default) Go module proxy https://proxy.golang.org/]], so things didn't really notice. This raises the interesting question of how you find this sort of thing, in all of at least three variations. Unfortunately, right now there are no great answers, but here's what I can see. The most straightforward case is if a module has been [[marked as entirely deprecated https://go.dev/ref/mod#go-mod-file-module]] or a module version has been [[marked as retracted https://go.dev/ref/mod#go-mod-file-retract]] in the module's go.mod. Marking the latest version of your module as retracted is actually somewhat complex; see the example in [[_retract_ directive https://go.dev/ref/mod#go-mod-file-retract]]. In both cases, you can find out about this with [['_go list -m -u all_' https://go.dev/ref/mod#go-list-m]], although it's mixed in with all of the other modules. I think that today, you can narrow the output down to only retracted and deprecated modules by looking for '(' in it: .pn prewrap on > go list -m -u all | fgrep '(' However, this will not help you if the upstream has removed the module entirely, or removed a version without doing the right [[_retract_ directive]] magic in go.mod. And using fgrep here counts on the Go authors not changing the format of the output for retracted or deprecated modules; as we've all found out in the module era, the Go tools are not a stable interface. (People who are very clever with Go templates may be able to craft a '_go list -m -f_' format that will only list deprecated modules and retracted module versions.) To detect a missing version or module, you need to defeat two opponents at once; [[the Go module proxy https://proxy.golang.org/]] and [[your local module cache https://go.dev/ref/mod#module-cache]]. Defeating the Go module proxy simple and is done by setting [[the _GOPROXY_ environment variable https://go.dev/ref/mod#environment-variables]] to '_direct_'. There is no direct way to disable the local module cache; instead, you have to set [[the _GOMODCACHE_ environment variable https://go.dev/ref/mod#environment-variables]] to a new, empty scratch directory before you run '_go mod list -m -u all_'. This gives you: > export GOPROXY=direct > export GOMODCACHE=/tmp/t-$$ > go list -m -u all This will be slow. If a module version has been removed, you'll get a relatively normal error message of 'invalid version: unknown revision v<...>', which is printed to standard error. If a module has been removed entirely, you will get a much more cryptic error that will probably complain something like 'invalid version: git ls-remote -q origin in : '. I'm not going to put the literal message I get here because I'm not sure anyone else would get the same one. Afterward, you'll want to remove your temporary GOMODCACHE (which has fortunately not been created with any non-writeable directories). If you intend to check a bunch of modules or programs at once, you don't have to clean and remake your scratch GOMODCACHE between each one; it's good enough that it has relatively recent contents. The other way to detect missing modules and module versions is to try to build all of your programs with these GOPROXY and GOMODCACHE environment variable settings (and afterward you'll need to do '_go clean -modcache_' to clean out this scratch module cache, which also removes your GOMODCACHE top level directory). If all programs build, all of their dependencies are still there (although some may be retracted or deprecated; '_go build_' or '_go install_' won't warn you about that). In some [[CI https://en.wikipedia.org/wiki/Continuous_integration]] environments you'll start with a completely clean environment every time, with no local module cache, so all you need to do is force '_GOPROXY=direct_' (of course, this will slow down builds; the Go module proxy is faster than direct fetching). It's possible that people have already written some third party programs to do all of this for you, in a more convenient form and with nicer output than you get from the normal Go tools (and to be fair, this isn't really the job of those tools). PS: The reason '_go build_' and '_go install_' generally won't warn you that you're using retracted versions or entirely deprecated modules is partly that by and large the retraction or deprecation won't be in the _go.mod_ of the version of the module you're currently using. Instead these will usually be in a later version, which Go will only look at if you ask it to look for module updates.