golang/go · error

can only use path@version syntax with 'go get' and 'go insta

Error message

can only use path@version syntax with 'go get' and 'go install' in module-aware mode

What it means

An import path or package argument containing an @ symbol (version qualifier, e.g., foo@v1.2.3) was used in a context that doesn't support it. The @version syntax is only valid with go get and go install in module-aware mode. Using it in other commands (go build, go run, go test) or in GOPATH mode triggers this error. The check fires during package loading when strings.Contains(path, '@') is true.

Source

Thrown at src/cmd/go/internal/load/pkg.go:863

func loadPackageData(ld *modload.Loader, ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) {
	ctx, span := trace.StartSpan(ctx, "load.loadPackageData "+path)
	defer span.Done()

	if path == "" {
		panic("loadPackageData called with empty package path")
	}

	if strings.HasPrefix(path, "mod/") {
		// Paths beginning with "mod/" might accidentally
		// look in the module cache directory tree in $GOPATH/pkg/mod/.
		// This prefix is owned by the Go core for possible use in the
		// standard library (since it does not begin with a domain name),
		// so it's OK to disallow entirely.
		return nil, false, fmt.Errorf("disallowed import path %q", path)
	}

	if strings.Contains(path, "@") {
		return nil, false, errors.New("can only use path@version syntax with 'go get' and 'go install' in module-aware mode")
	}

	// Determine canonical package path and directory.
	// For a local import the identifier is the pseudo-import path
	// we create from the full directory to the package.
	// Otherwise it is the usual import path.
	// For vendored imports, it is the expanded form.
	//
	// Note that when modules are enabled, local import paths are normally
	// canonicalized by modload.LoadPackages before now. However, if there's an
	// error resolving a local path, it will be returned untransformed
	// so that 'go list -e' reports something useful.
	importKey := importSpec{
		path:        path,
		parentPath:  parentPath,
		parentDir:   parentDir,
		parentRoot:  parentRoot,
		parentIsStd: parentIsStd,

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Use go get or go install for version-qualified packages: 'go install foo@v1.2.3' instead of 'go build foo@v1.2.3'
  2. If you need a specific version for building, run 'go get foo@v1.2.3' first to update go.mod, then 'go build ./...'
  3. Ensure GO111MODULE is not set to off — use 'on' or 'auto' (the default in modern Go)
  4. Remove any @version syntax from import paths in source code — version pinning belongs in go.mod, not in import statements

Example fix

// before: using @version with wrong command
// $ go build golang.org/x/tools/cmd/goimports@latest
// # error: can only use path@version syntax with go get and go install

// after: use go install for version-qualified packages
// $ go install golang.org/x/tools/cmd/goimports@latest

// or for building local code with a specific dependency version:
// $ go get golang.org/x/text@v0.14.0
// $ go build ./...
Defensive patterns

Strategy: validation

Validate before calling

// Validate that import paths and package arguments don't use @version
// in contexts that don't support it.
func validatePackageArg(path string, command string, moduleMode bool) error {
    if strings.Contains(path, "@") {
        if !moduleMode {
            return fmt.Errorf("path@version requires module mode (GO111MODULE=on)")
        }
        if command != "get" && command != "install" {
            return fmt.Errorf("path@version only supported with go get and go install")
        }
    }
    return nil
}

// Check if module mode is active:
func isModuleMode() bool {
    mode := os.Getenv("GO111MODULE")
    return mode != "off" // "on", "auto", or empty all enable modules in modern Go
}

Type guard

// This is a package loading error, returned as a plain error.
// Detect by message:
func isAtVersionError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "path@version syntax")
}

Try / catch

// For tooling that loads packages:
// pkgs, err := packages.Load(cfg, pattern)
// if err != nil {
//     if isAtVersionError(err) {
//         // User passed foo@version with an unsupported command.
//         // Strip the version or suggest go get/go install.
//         base := path[:strings.Index(path, "@")]
//         fmt.Printf("Use 'go get %s' to fetch the version, then rebuild\n", pattern)
//         fmt.Printf("Or use 'go install %s'\n", pattern)
//     }
// }

Prevention

When it happens

Trigger: Package loading in load/pkg.go encounters strings.Contains(path, '@') == true during import path resolution. This happens when a package argument or import path contains @ but the current command is not go get/go install, or when GO111MODULE=off (GOPATH mode) is active.

Common situations: Running go build or go run with a package@version argument (e.g., 'go build foo@v1.2.3'); using @version syntax in an import statement in source code; running in GOPATH mode (GO111MODULE=off) where version qualifiers aren't supported; using @version with go list or other commands that don't support it; misunderstanding module-mode semantics.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/b8f96576c0e82c42. Report an issue: GitHub.