Fixing the '410 Gone' Error with Private Go Modules

intermediate🔷 Go2026-07-28| Go 1.13+, Linux/macOS/Windows, Private GitHub/GitLab/Bitbucket repositories

Error Message

go get: module github.com/your-org/private-repo: reading https://proxy.golang.org/github.com/your-org/private-repo/@v/list: 410 Gone
#golang#go-modules#devops#git

The 30-Second Fix

The error occurs because the public Go Proxy (proxy.golang.org) cannot see your private code. To fix this, tell Go to bypass the proxy for your specific organization. Run this command in your terminal:

go env -w GOPRIVATE=github.com/your-org/*

Working with multiple internal domains? Separate them with commas. For example, if you use both GitHub and a self-hosted GitLab, use:

go env -w GOPRIVATE=github.com/your-org/*,gitlab.mycompany.com/*

Why does '410 Gone' happen?

Since the release of Go 1.13, the GOPROXY variable defaults to https://proxy.golang.org,direct. This means every time you run go get, your machine asks Google's public proxy for the code first.

When that proxy tries to fetch a private repository, it hits an authentication wall. Instead of returning a 403 Forbidden—which would confirm to the world that a private repo exists—the proxy returns 410 Gone. This security measure keeps your private project names hidden from the public. The proxy is effectively saying, "I don't know what this is, and I can't serve it to you."

The Go toolchain stops immediately when it receives this 410 status. It won't try a direct connection unless you explicitly tell it which paths are private.

Effective Solutions

1. Define Your Private Domains

Setting GOPRIVATE is the most reliable way to fix this. It acts as a bypass list for module paths. When a path matches this pattern, Go ignores the proxy and the public checksum database (SumDB) entirely.

For a specific repository:

export GOPRIVATE=github.com/username/my-project

For an entire company (Best Practice):

go env -w GOPRIVATE=github.com/acme-corp/*

2. Force Git to Use SSH

Even after fixing GOPRIVATE, your build might fail with a "terminal prompts disabled" error. This happens because Go tries to fetch modules via HTTPS, but your environment uses SSH keys for authentication. You can trick Git into swapping the protocol automatically:

git config --global url."git@github.com:your-org/".insteadOf "https://github.com/your-org/"

This command tells Git: "Whenever you see a request for https://github.com/your-org/, use git@github.com:your-org/ instead." Now, the Go tool can use your local ~/.ssh/id_rsa or ed25519 keys to log in.

3. Handling CI/CD and Docker

In automated environments like GitHub Actions or Jenkins, you cannot use go env -w because those environments are often ephemeral. Instead, pass these as standard environment variables in your pipeline script or Dockerfile.

Example Dockerfile snippet:

# Set Go to bypass proxy for internal modules
ENV GOPRIVATE=github.com/your-org/*

# Use a Personal Access Token (PAT) for private access
RUN git config --global url."https://${GITHUB_TOKEN}:x-oauth-basic@github.com/your-org/".insteadOf "https://github.com/your-org/"

Verifying the Fix

Confirm your settings are active by checking the environment:

go env GOPRIVATE

Next, try fetching the module with the verbose flag. This allows you to see exactly where Go is looking for the files:

go get -v github.com/your-org/private-repo@latest

If the configuration is correct, you will see Git cloning the repository directly from your source provider. You will no longer see references to proxy.golang.org for that specific module.

Common Mistakes

  • Syntax Errors: Ensure there are no spaces around the = sign. GOPRIVATE = github... will fail in most shells.
  • Checksum Failures: If you manually set GONOPROXY but forget GONOSUMDB, your build will crash. The public checksum database cannot verify private code. Using GOPRIVATE is better because it configures both settings at once.
  • Wildcard Scope: If your module is at github.com/org/sub-folder/repo, the wildcard github.com/org/* will cover it. However, github.com/org (without the asterisk) might not.

Related Error Notes