Go version
go version go1.24.3 darwin/arm64
Output of go env in your module/workspace:
AR='ar'
CC='cc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='c++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/anuraag/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/anuraag/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/vx/38td0k79201f9zn_myzbqx_40000gn/T/go-build645842018=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Users/anuraag/git/go-build/go.mod'
GOMODCACHE='/Users/anuraag/go/pkg/mod'
GONOPROXY='github.com/tetrateio/*'
GONOSUMDB='github.com/tetrateio/*'
GOOS='darwin'
GOPATH='/Users/anuraag/go'
GOPRIVATE='github.com/tetrateio/*'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.24.3/libexec'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/anuraag/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.24.3/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.24.3'
GOWORK='/Users/anuraag/git/go-build/go.work'
PKG_CONFIG='pkg-config'
What did you do?
go tool -modfile build/tools/golangci-lint/go.mod golangci-lint run -h
Note, go.work does not include ./build/tools/golangci-lint. build/tools/golangci-lint/go.mod contains single tool github.com/golangci/golangci-lint/v2/cmd/golangci-lint and the dependencies added by go mod tidy.
What did you see happen?
go: -modfile cannot be used in workspace mode
What did you expect to see?
Tool runs normally. I would like to use separate mod files for tools to protect against dependency conflicts. Unfortunately, -modfile cannot be used in a workspace (#59996).
It does work if specifying GOWORK=off, but for tools that build Go code, such as golangci-lint (or perhaps opentelemetry-go-autoinstrumentation, etc), this causes the downstream tool invocation to inherit the variable and generally not work if the workspace settings are required to build the code. It seems like it should be possible to run tools with isolated modfiles within a workspace.
A couple of ideas
-
Respect
-modfilespecifically for thetoolcommand if the tool module is not in the workspace (my current issue is specific totoolbut the same may apply toruninstead of blocking the flag completely like now). IIUC #59996 correctly, the corner case is specifically running a workspace module with the flag set and there wouldn't be problems for modules not defined in the workspace? -
Add a command line flag with the same semantics as
GOWORK, e.g.go tool -gowork off -modfile tools/golangci-lint/go.mod run. This would allow configuringgo toolwithout affecting the downstream invocation. Unfortunately, the best named-workflag is already taken.
Comment From: gabyhelp
Related Issues
- cmd/go: reject the `-modfile` flag in workspace mode #59996 (closed)
- x/website: ref/mod still references the deleted -workfile flag #51838 (closed)
- cmd/go: workspace detected outside of workspace #51604 (closed)
- cmd/go: go work init won't create nested workspaces #53938
- x/tools/gopls: deprecate the "allowModfileModifications" setting #56570 (closed)
- cmd/go: default `-mod=vendor` behavior unexpectedly present in workspace mode #54130 (closed)
- cmd/go: workspace recursive add should skip malformed module definitions #51959
- cmd/go/internal/modload: reject the -modfile flag in workspace mode #60033 (closed)
Related Code Changes
- cmd/go: report a helpful error when there are no modules in workspace
- cmd/go/internal/modload: reject the -modfile flag in workspace mode
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: matloob
One of the principles of the way the tool directive was designed is that the tools go in the same module graph as the rest of your code. That does mean that there are some cases where you'd have to build the tool using go build, perhaps in another workspace before you run it.
We could have gone with another design, but given that this is the way it works now, adding multiple ways of specifying the module graph could just make things more complex, and we'd need to hear a compelling justification to do so.
Comment From: anuraaga
@matloob But tool supports the -modfile flag which is now also fully documented
https://github.com/golang/go/commit/b574590c36b7ede1492239db2d55c35e8818c7a7
So already there are multiple ways of specifying the module graph right? This is good since there can otherwise be some dependency conflicts.
This issue is mostly about that not working in workspace mode though it seems like it should, not adding a new mechanism for the dependency graph.
Comment From: lieut-data
Hey all, chiming in from Mattermost here. We were really excited about the potential to simplify and speed up this common pattern in our build tooling:
golangci-lint: ## Run golangci-lint on codebase
$(GO) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6
$(GOBIN)/golangci-lint run ./... ./public/...
We weren't comfortable with the idea of expanding the module graph for our core product and so hoped to fallback to the tools.mod approach -- until we ran into this workspace limitation. We're presently discussing abandoning go tool altogether given these limitations.
Totally understand that our choices aren't aligned with the go1.24 vision for go tool, but wanted to volunteer a data point going forward.
Comment From: seankhliao
I'll close since this is consistent with the rest of the go command, i.e you can't build regular packages with -modfile either.
Comment From: anuraaga
@seankhliao Can you clarify what you mean by build regular packages? We're talking about running external commands. I tried building an external package, and modfile or not it's not supported so I think it may not be related
❯ go build -o prettier github.com/seanhkliao/mono/cli/fin@latest
package github.com/seanhkliao/mono/cli/fin@latest: can only use path@version syntax with 'go get' and 'go install' in module-aware mode
Another point is that we are sticking to go run instead of go tool because of the issue here and a priority on devex - but this has security implications by not locking dependencies :( It seems like something that should continue to be considered by the feature owners, not just autoclosed.
Comment From: anuraaga
No high hopes this comment will be read, but I randomly noticed golangci-lint documenting the separate modfile pattern for go tool
https://golangci-lint.run/docs/welcome/install/#install-from-sources
(Under "go tool usage recommendations")
But as this issue states, this works outside of workspace, but not within workspace, which seems like an incorrect limitation. @matloob @seankhliao Does this note from the most popular tool suggest more discussion is warranted here?