Question
A Go project that previously built successfully now fails with this error when I build a package:
start.go: package project/game is not in GOROOT (C:\Go\src\project\game)
My folders are arranged under C:\Users\username like this:
src/
└── project/
├── game/
│ ├── entity/
│ │ └── whatever.go
│ └── game_stuff.go
└── server/
My environment variables are:
GOROOT=C:\Go
GOPATH=C:\Users\ketchup\go
I ran go mod init separately for project/game/entity, project/game, and project/server. GoLand runs the following command when building:
C:\Go\bin\go.exe build -o C:\Users\ketchup\AppData\Local\Temp\___go_build_project_server.exe project/server
Why is Go searching in GOROOT, and how should I structure the project and modules so that project/server can import project/game correctly?
Short Answer
You will learn why an unresolved Go import can produce a “package is not in GOROOT” message, how Go modules determine import paths, and how to organize related packages under one module. You will also see when GOPATH matters and which go build command to run from a module-based project.
Concept
Go needs to map every import path, such as:
import "example.com/project/game"
to source code on disk. The way it performs that mapping depends on whether the project uses Go modules or the older GOPATH workspace workflow.
In a modern Go module project, a go.mod file defines the module's import-path prefix:
module example.com/project
With that module declaration, a directory named game beside go.mod is imported as:
import "example.com/project/game"
A directory named server is another package in the same module, not another module.
The error:
package project/game is not in GOROOT (C:\Go\src\project\game)
means Go could not resolve the import as a package in the current module, a required dependency module, or the configured workspace. It then reports the location where it checked in the Go installation. GOROOT is where Go itself is installed, often C:\Go; application code normally does not belong there.
A common cause is creating separate go.mod files for directories that are really packages of one application. Once game has its own module, it is no longer automatically part of the server module. Separate modules require explicit versioned dependencies, a local replace directive, or a Go workspace. For a single application, one module at the shared root is simpler and usually correct.
GOPATH is mainly relevant for older projects that do not use modules and for locations such as the Go binary cache. In module-based development, source code can live outside GOPATH.
Mental Model
Think of a module as a building with one street address.
- The
moduleline ingo.modis the building's address, for exampleexample.com/project. - Each subdirectory is a room in that building:
game,game/entity, andserver. - An import path is the full address of a room:
example.com/project/game.
If every room gets its own building registration (go.mod), they are no longer automatically connected. To visit another building, Go needs explicit directions: a dependency version, a replace rule, or a workspace.
GOROOT is the Go toolchain's own building. Go checking there does not mean your code should be moved there; it usually means Go did not find your requested address in the places it expected.
Syntax and Examples
For one application containing game and server, use one module at the shared root.
project/
├── go.mod
├── game/
│ ├── game.go
│ └── entity/
│ └── player.go
└── server/
└── main.go
Create the module from the project directory:
cd C:\Users\ketchup\project
go mod init example.com/ketchup/project
go mod tidy
go.mod should contain one module declaration:
module example.com/ketchup/project
go 1.22
Use the Go version installed on your computer. A repository hosted at
github.com/name/projectwould normally use that URL as its module path.
Then server/main.go can import the sibling game package:
package main
import (
"fmt"
"example.com/ketchup/project/game"
)
func main() {
fmt.Println(game.Message())
}
And game/game.go provides an exported function:
package game
func Message() string {
return "Game package loaded"
}
Build or run from the module root:
go run ./server
go build ./server
go build ./...
The ./server form means “the directory named server relative to the current directory.” It avoids relying on a bare import path such as project/server.
Step by Step Execution
Consider this project:
project/
├── go.mod # module example.com/ketchup/project
├── game/
│ └── game.go # package game
└── server/
└── main.go # package main
server/main.go contains:
package main
import (
"fmt"
"example.com/ketchup/project/game"
)
func main() {
fmt.Println(game.Message())
}
When you run this from project:
go run ./server
Go performs these steps:
- It sees
./serverand locates theserverdirectory relative to the current directory. - It walks upward from that directory until it finds
project/go.mod. - It reads the module path:
example.com/ketchup/project. - It sees the import
example.com/ketchup/project/game. - Because that import begins with the current module path, it maps the remaining
/gameto the localproject/gamedirectory. - It compiles
game, then compilesserver, and finally runs the resulting executable.
If game/go.mod exists with a different module declaration, step 5 no longer treats game as an ordinary package within the root module. That is why accidental nested modules often cause confusing import errors.
Real World Use Cases
Go modules and correct import paths are used in nearly every Go project:
- Web APIs: a
cmd/apiexecutable imports internal packages such asexample.com/shop/api/handlersandexample.com/shop/api/database. - Command-line tools: a
cmd/toolcommand imports reusable logic from packages such asconfig,parser, andservice. - Background workers: a worker package imports shared domain code from packages such as
jobs,models, orqueue. - Monorepos: several independently released services may use separate modules, coordinated with a
go.workworkspace during local development. - Libraries: a public module path tells downstream users exactly what to import and version, such as
github.com/org/library/parser.
Real Codebase Usage
Most Go repositories use one module for one deployable application or one versioned library.
A typical layout is:
example-app/
├── go.mod
├── cmd/
│ └── api/
│ └── main.go
├── internal/
│ ├── config/
│ └── service/
└── pkg/
└── optionalpublicpackage/
Common project practices include:
- One root
go.mod: packages below it use imports beginning with the module path. - Relative package commands: developers run
go test ./...,go vet ./..., andgo build ./cmd/apifrom the module root. internalpackages: code underinternal/can be imported only by code in the allowed parent tree, helping keep implementation details private.- Dependency cleanup:
go mod tidyadds missing dependency requirements and removes unused ones after imports change. - Explicit multi-module setup: when separate modules are intentional, each module has its own
go.mod; local development commonly uses ago.workfile or carefully scopedreplacedirectives.
For the project in the question, remove the go.mod files inside game, entity, and server if they are all parts of one application. Keep one go.mod in the common project directory, then update imports to match its module declaration.
Common Mistakes
Creating a module for every package
This creates independent dependency boundaries unnecessarily:
project/go.mod
game/go.mod
server/go.mod
For a single application, use only:
project/go.mod
project/game/
project/server/
Importing a directory name instead of the module path
If go.mod says:
module example.com/ketchup/project
this import is wrong:
import "project/game"
Use the full module-based import instead:
import "example.com/ketchup/project/game"
Putting application code in GOROOT
Do not copy project packages into C:\Go\src. GOROOT belongs to the installed Go distribution. Keep it managed by the Go installer unless you are building Go itself.
Mixing a GOPATH-style folder with module assumptions
In old GOPATH mode, project/game would need to be located at:
%GOPATH%\src\project\game
But the listed source path and GOPATH do not match. More importantly, modern projects should generally use modules and not depend on this layout.
Building a bare import path from the wrong context
This command asks Go to resolve project/server as an import path:
go build project/server
From the module root, prefer:
go build ./server
Ignoring the active module in an IDE
GoLand uses the Go toolchain and the project/module configuration. Open the folder containing the intended root go.mod, then refresh Go modules or reopen the project after moving or deleting go.mod files.
Comparisons
| Approach | How packages are located | Recommended use |
|---|---|---|
| Go modules | go.mod module path plus directories and declared dependencies | Default for modern Go projects |
| GOPATH workspace | %GOPATH%/src/<import-path> directory layout | Maintaining legacy projects |
| One module, many packages | Subdirectories under one root go.mod | One application or library with related packages |
| Multiple modules | Each module has its own go.mod and dependency graph | Independently versioned components |
go work workspace | A go.work file connects local modules | Local development across intentional multiple modules |
A single module does not mean a single package. One module can contain many packages. A package is determined by a directory and its package declaration; a module is the larger unit that defines import-path ownership and dependencies.
Cheat Sheet
GOROOT = Go installation directory
GOPATH = legacy workspace location and Go workspace-related paths
go.mod = module definition and dependency list
Create one module at the application root:
cd path\to\project
go mod init example.com/you/project
go mod tidy
Map directories to import paths:
go.mod module: example.com/you/project
project/game -> example.com/you/project/game
project/game/entity -> example.com/you/project/game/entity
Useful commands from the module root:
go run ./server
go build ./server
go build ./...
go test ./...
go mod tidy
go env GOROOT GOPATH GOMOD
Rules to remember:
- Do not put ordinary application code in
GOROOT. - Do not create
go.modin every package of one application. - Imports must start with the module path declared in
go.mod. - Use
./directoryto target a local package directory. - If a directory intentionally has its own
go.mod, it is a separate module.
FAQ
Why does Go say a package is not in GOROOT?
Go could not resolve the import through the current module, required modules, or workspace. The message shows that it also checked the Go installation source tree. Your application package usually does not belong in GOROOT.
Should I set GOPATH for a Go modules project?
Usually not for locating your project source. Module-based projects can live anywhere. GOPATH may still be used by Go for workspace-related directories and installed binaries.
Should every Go folder have a go.mod file?
No. Create a go.mod for each independently versioned module, not for every package directory. Most small applications need one root go.mod.
How do I know which module Go is using?
From the relevant directory, run:
go env GOMOD
It prints the path to the active go.mod, or an empty value when no module is active.
Why does go build ./server work differently from go build project/server?
./server is a filesystem-relative package pattern. project/server is treated as an import path that Go must resolve through module or GOPATH rules.
Can I use module project in go.mod?
It can work locally, but a globally unique module path such as github.com/yourname/project or example.com/yourname/project is better, especially if the code may be shared or published.
When should I use go.work?
Use go.work when you intentionally develop multiple separate modules together. It is not necessary when the directories are simply packages of one application.
Does GoLand cause this error?
Usually the underlying issue is Go module discovery, imports, or the build command. GoLand may expose it by opening the wrong directory or using a stale module configuration, but the Go command-line tools should be fixed first.
Mini Project
Description
Create a small command-line application with a server command that imports a sibling game package from the same Go module. This demonstrates the relationship between a module path, directory structure, imports, and relative build commands.
Goal
Build and run a command that prints a message returned by a local package.
Requirements
Requirement 1
Keep learning
Related questions
Are Go Maps Passed by Value or Reference?
Learn Go map parameter and return semantics: maps are passed by value, while copies share underlying data. Know when map pointers are useful.
Authentication for Go REST APIs: Sessions, Tokens, and Middleware
Learn practical authentication patterns for Go REST APIs, including password hashing, server sessions, bearer tokens, middleware, and security rules.
Automatic Build Versioning in Go: Embed Incrementing Build Numbers
Learn how to add automatic build versioning in Go using linker flags, build metadata, CI counters, and Git-based version values.