Go “Cannot Find Package” / Not in GOROOT (Even If GOPATH Is Set)

Why Go says cannot find package or package is not in GOROOT (or GOROOT/GOPATH), how modules fix it, and fixes for go build, go install, and the -o with multiple packages error.

Published

Updated

Read time 5 min read

Reviewed byDeepak Prasad

Go “Cannot Find Package” / Not in GOROOT (Even If GOPATH Is Set)

When go build or go install stops with “cannot find package” or “package … is not in GOROOT” (sometimes mentioning GOROOT or GOPATH), it almost always means Go cannot match your import line to any real folder it is allowed to use—not that your GOPATH environment variable forgot to turn on. People still hit this after setting GOPATH because imports today are ruled mainly by modules (go.mod) and the directory tree under your project, not by a loose file sitting somewhere under src.

This guide walks through what that message is trying to tell you, how to fix layout under Go modules (the path you should use today), and a couple of related errors that show up in the same searches (including “cannot use -o with multiple packages”).

If you are new to modules, import local package without GOPATH is a good companion read.

Tested with Go 1.26.4 linux/amd64 on Linux kernel 6.14.0-37-generic.


Understanding “cannot find package” and “not in GOROOT”

GOROOT is where Go keeps the standard library (fmt, net/http, and so on). When the compiler says a package is “not in GOROOT,” it is not accusing you of a broken Go install; it is saying this import is not a built-in package, and Go still has not found it anywhere else it is allowed to look.

In module mode (the default for years, and the only mode on current Go versions), “anywhere else” means roughly: other packages in your module, other modules listed in go.mod, and the module download cache—not “any folder on disk you happen to like.”

So searches like “cannot find package in goroot,” “package is not in goroot,” or “cannot find package in goroot or gopath” all point to the same troubleshooting job: line up your import path with a real directory and a correct go.mod module line.


Put your code in a folder with a go.mod file. The module line is the prefix of every import inside that tree.

The in-site Run control sends one program string to the Go Playground. The demo/ example below is two packages on disk (package boo in boo/boo.go and package main importing demo/boo). That cannot compile as a single Playground paste, so those Go fences use {run=false}—create the files and use go run . locally. A self-contained package main that only imports the standard library does get Run:

go
package main

import "fmt"

func main() {
	fmt.Println("When imports resolve, the compiler is happy—this program only needs the stdlib.")
}
Output

If you use Run on that snippet, you should see one line of printed output from fmt.Println.

Example layout:

text
demo/
  go.mod          # module demo
  main.go
  boo/
    boo.go        # package boo

go.mod:

text
module demo

go 1.21

boo/boo.go:

go
package boo

import "fmt"

func Boo() {
	fmt.Println("This is the Boo function")
}

main.go:

go
package main

import (
	"demo/boo"
	"fmt"
)

func main() {
	boo.Boo()
	fmt.Println("This is the main call")
}

From the demo directory:

bash
go run .

After go run . from the demo root you should see the Boo line first, then the line from main.

Typical mistakes that reproduce “go cannot find package” or “golang cannot find package”:

  • main.go calls boo.Boo() but there is no import "demo/boo" (or whatever your module prefix is).
  • boo.go sits next to main.go while the code still says package boo—the folder name and package line should match, and the file should live under boo/, not beside main unless you intentionally use package main in one file only.
  • The import uses myproject/boo but go.mod says module github.com/you/myproject—the prefix in import must match the module path plus subfolders.

After you move files, run:

bash
go mod tidy

…so missing requirements are recorded or stale entries are cleaned up.

go build and go install

go build and go install both resolve imports the same way. If you see go build report “cannot find package” (or the same from go install), apply the same layout checks as above. go install additionally writes a binary to GOBIN or GOPATH/bin when the build succeeds—it does not magically find packages GOPATH could not see.

Dot imports, replace, and “cannot find package . …”

A dot import (import . "some/pkg") or a bad relative path often triggers confusing errors. Prefer normal imports (import "module/subpkg") until you are comfortable with the rules. If you truly need a local path outside the module, add a replace directive in go.mod pointing at a folder on disk, then import the module path you replaced—not a raw filesystem path in the import string.

go build -o with multiple packages

If you run something like:

bash
go build -o mytool ./cmd/foo ./cmd/bar

Go may report:

text
go: cannot use -o with multiple packages

You asked for one output file name (-o) but listed more than one package. Build one main package at a time, for example:

bash
go build -o mytool ./cmd/foo

…or drop -o and build each package separately.


Legacy GOPATH note

Long ago, people put everything under $GOPATH/src/import/path. Current Go expects modules for new work. Setting GOPATH alone does not make import "boo" work unless the source really lives at $GOPATH/src/boo and you are still on a workflow that uses GOPATH mode—which modern toolchains no longer emphasize.

If you maintain very old material, the official note on defaults is Go 1.16 module changes. For day-to-day fixes, treat a correct go.mod plus matching import paths as the real answer—not flipping historical environment variables.


Summary

“Cannot find package” and “not in GOROOT” mean the import string did not resolve to a real package: fix the module path in go.mod, put code under folders that match package names, add the correct import, and run go mod tidy. go build and go install fail the same way when imports are wrong. If you see “cannot use -o with multiple packages,” you passed more than one package to a command that only allows one output binary name. Modern Go is module-first; do not expect GOPATH alone to fix a mismatched import.


References


Frequently Asked Questions

1. Why does Go say the package is not in GOROOT?

GOROOT is where the standard library lives. That message means Go did not find your import as a standard package and then could not resolve it from your module or GOPATH layout—so it names GOROOT as one of the places it looked.

2. My GOPATH is set; why does go build still say cannot find package?

Modern Go uses modules by default. GOPATH being set does not automatically make a random folder importable; the import path must match your go.mod module path and directory layout, or you need a replace directive for local experiments.

3. Is go install different from go build for this error?

Same cause: both commands need to resolve imports first. If the package path is wrong or missing, both fail with the same class of cannot find package style errors.

4. What does go cannot use -o with multiple packages mean?

You passed more than one package pattern to go build or go install together with -o. Use -o only when building a single main package, or drop -o and let Go write binaries to the default location, or build packages one at a time.
Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise …