{"record":{"id":"042a0a28165d1809","repo":"golang/go","slug":"network-disabled-by-v-v","errorCode":null,"errorMessage":"network disabled by %v=%v","messagePattern":"network disabled by (.+?)=(.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/base/limit.go","lineNumber":48,"sourceCode":"\t\tif err != nil {\n\t\t\tFatalf(\"invalid %s: %v\", NetLimitGodebug.Name(), err)\n\t\t}\n\t\tif n < 0 {\n\t\t\t// Treat negative values as unlimited.\n\t\t\treturn\n\t\t}\n\t\tnetLimitSem = make(chan struct{}, n)\n\t})\n\n\treturn cap(netLimitSem), netLimitSem != nil\n}\n\n// AcquireNet acquires a semaphore token for a network operation.\nfunc AcquireNet() (release func(), err error) {\n\thasToken := false\n\tif n, ok := NetLimit(); ok {\n\t\tif n == 0 {\n\t\t\treturn nil, fmt.Errorf(\"network disabled by %v=%v\", NetLimitGodebug.Name(), NetLimitGodebug.Value())\n\t\t}\n\t\tnetLimitSem <- struct{}{}\n\t\thasToken = true\n\t}\n\n\tchecker := new(netTokenChecker)\n\tcleanup := runtime.AddCleanup(checker, func(_ int) { panic(\"internal error: net token acquired but not released\") }, 0)\n\n\treturn func() {\n\t\tif checker.released {\n\t\t\tpanic(\"internal error: net token released twice\")\n\t\t}\n\t\tchecker.released = true\n\t\tif hasToken {\n\t\t\t<-netLimitSem\n\t\t}\n\t\tcleanup.Stop()\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/base/limit.go#L30-L66","documentation":"Returned by AcquireNet() when the GODEBUG-controlled network limit (NetLimitGodebug) is set to 0, which disables all network access by the go command. The go command funnels every network operation (module/proxy fetches, VCS traffic) through a single semaphore (netLimitSem); a zero cap means no token can ever be acquired. This is an intentional kill-switch for offline/air-gapped builds, surfaced as a hard error so callers stop before touching the network.","triggerScenarios":"Calling base.AcquireNet() while the effective GODEBUG net-limit setting resolves to 0 (the limit is configured via NetLimitGodebug, e.g. GODEBUG=...=0). Any go command path that reaches a network operation (go get, module download, VCS sync) will trip it.","commonSituations":"Reproducible/offline CI that pins GODEBUG to disable network; sandboxed build environments; users who copied a GODEBUG value from a hardening guide without understanding the net limit; GOPROXY=off builds that also set the limit.","solutions":["Unset or raise the GODEBUG net-limit setting so NetLimit() returns a positive value (remove the =0 token from $GODEBUG).","If network must stay off, run with a vendor directory (GOFLAGS=-mod=vendor) so no AcquireNet path is hit.","If the limit is being set unintentionally, inspect `go env GODEBUG` and your shell/toolchain config to find the source.","For programmatic callers, call base.NetLimit() first and skip the network path when ok && n==0 instead of erroring."],"exampleFix":"// before: network op attempted with GODEBUG net limit = 0\n//   -> error: network disabled by <godebug>=0\n//\n// after: drop the net-limit override from GODEBUG\n$ GODEBUG=$(echo \"$GODEBUG\" | tr , '\\n' | grep -v '^netlimit=0$' | paste -sd,) go mod download","handlingStrategy":"validation","validationCode":"if n, ok := base.NetLimit(); ok && n == 0 {\n    // network is disabled by GODEBUG; skip the network path\n    return ErrOffline\n}\nrelease, err := base.AcquireNet()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Inspect `go env GODEBUG` before relying on network in sandboxed builds.","Pin GODEBUG in CI from a single documented source so the net limit is intentional.","For air-gapped builds, prefer GOFLAGS=-mod=vendor over disabling the net limit."],"tags":["network","godebug","configuration","offline"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}