Skip to content

cmd/go: get hangs without error output from unknown revisions #53905

@Justin-W

Description

@Justin-W

What version of Go are you using (go version)?

$ go version
go version go1.18.4 darwin/arm64

$ git version
git version 2.37.1

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env

% go env
GO111MODULE="auto"
GOARCH="arm64"
GOBIN=""
GOCACHE="REDACTED"
GOENV="REDACTED"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="REDACTED"
GONOPROXY="REDACTED"
GONOSUMDB="REDACTED"
GOOS="darwin"
GOPATH="REDACTED"
GOPRIVATE="REDACTED"
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.18.4"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/vy/ryp4d95n75q5j6kf58hc551m0000gn/T/go-build559884269=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

  1. Create/identify 3 go modules/repos: A depended on by B depended on by C (so C indirectly depends on A)
  2. make B's go.mod reference to A invalid
    (for us, A's git history was rewritten; but you could probably manually edit B's go.mod with a invalid pseudo-version to get the same effect)
  3. run go get -u ./... in either B or C (or any module that depends on either of them)
  4. wait for the go process to hang with high CPU, then terminate it
  5. run go list -m -u -json all | jq --raw-output 'select((.Indirect or .Main)|not) | .Path' | xargs -t -I % go get -u -t %@latest, to find any "error:" or "panic:" output
  6. Revert any changes to go.* files resulting from step 5.

What did you expect to see?

Either some output indicating the dependency reference problem(s), or else normal operation of the go get ... command in step 3.

What did you see instead?

Step 3 starts running normally (there may or may not be some output, downloads, etc., with typical levels of CPU by the process), but at some point all output ceases and CPU spikes to 350%-450% and stays basically flat at that level until the go process is terminated.

Step 5 did not hang, and output contained several sections with errors like these:

go: downloading github.com/private-org/module-two v0.0.0-20220713230938-ae346380ff64
go: github.com/private-org/module-one@v0.0.0-20220203083605-df6cd891c11a: invalid version: unknown revision df6cd891c11a
go get -u -t github.com/private-org/module-three@latest
go: github.com/private-org/module-one@v0.0.0-20220203083605-df6cd891c11a: invalid version: unknown revision df6cd891c11a

Workaround

  1. Add a replace directive for each of the "invalid version"s identified in step 5 to the go.mod files of each dependent repo (including indirectly-dependent ones).
  2. Repeat steps 3 through 7 until step 3 finishes normally (i.e. without hanging)

Notes:

  • The hanging behavior happened consistently (100% repeatable; always hanged) on only some of the M1 macs tested. Others with identical hardware and similar go, git, etc. versions, even when running exactly the same commands on the same repos. Not sure why the issue only affected some envs and not others.
  • The root cause for us was that 3 repos had at least 1 pseudo-version reference (by other repos) to a commit which no longer existed in the referenced repo. Once the workaround above was completed for each missing revision, the unexpected go get behavior ceased.
    • I only identified a current go.mod reference to 1 of the 4 "missing revision"s which were in the error output. The other 3 seemed to be referenced exclusively from historical versions of go.mod and go.sum files (e.g. the git history of no-longer-referenced versions of certain modules), but not by any versions which were still directly referenced. IDK how un-referenced versions' go.* contents could still be affecting go get behavior, but it seemed to be the case. Very weird. If true, more details would be appreciated, since that might indicate that the replace directives need to remain in place forever (which would be unfortunate).
  • All repos involved are private repos, but IDK whether that matters or not. I suspect not. (All of the usual "private repo"-related config issues are not an issue for us, since all commands work fine on some machines, and work fine for repos with un-corrupted go.* files even on affected envs.)
  • The hanging happened with latest git and go versions (installed yesterday morning), and also with older versions of go (v1.18) and git. (IDK whether the git version matters or not, since upgrading seemed to have no effect.)
  • All of the repos involved had go 1.17 or go 1.18 directives in their go.mod files. We weren't attempting to preserve pre-v1.17 compatibility.
  • Adding git tags with names equal to the missing pseudoversions (e.g. v0.0.0-20220203083605-df6cd891c11a) did not work as a workaround.
    • It would be nice to have a tag-based way to retroactively "fix" go.mod refs which get broken as a result of commits which get irrevocably deleted. That would be much preferred vs the replace directives workaround.
  • Adding retract directives to the repos which were the source of the "missing" versions did not resolve the problem. (Would've been much nicer if it had, so that the same replace directives didn't need to be replicated in dozens of dependent repos.)
    • I know that retract isn't intended to prevent a dependent repo from referencing a retracted version once it already is, but since I was actually trying to upgrade all the deps, it would've been nice if the go get -u ./... command simply updated the "bad" refs with good ones (and didn't hang), which would have allowed me to iteratively upgrade all dependencies to stop using the bad revisions (without the need to manually identify and replace the "missing" revisions).

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeGoCommandcmd/goNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.WaitingForInfoIssue is not actionable because of missing required information, which needs to be provided.modules

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions