golang/go · error

GOROOT/src is not an importable package

Error message

GOROOT/src is not an importable package

What it means

`$GOROOT/src` is the directory that contains the standard library, but it is not itself an importable Go package. The loader returns this sentinel (errPkgIsGorootSrc) when something asks it to load that exact directory as a package.

Source

Thrown at src/cmd/go/internal/modload/load.go:682

	if pkg == "" {
		dirstr := fmt.Sprintf("directory %s", base.ShortPath(absDir))
		if dirstr == "directory ." {
			dirstr = "current directory"
		}
		if ld.inWorkspaceMode() {
			if mr := findModuleRoot(absDir); mr != "" {
				return "", fmt.Errorf("%s is contained in a module that is not one of the workspace modules listed in go.work. You can add the module to the workspace using:\n\tgo work use %s", dirstr, base.ShortPath(mr))
			}
			return "", fmt.Errorf("%s outside modules listed in go.work or their selected dependencies", dirstr)
		}
		return "", fmt.Errorf("%s outside main module or its selected dependencies", dirstr)
	}
	return pkg, nil
}

var (
	errDirectoryNotFound = errors.New("directory not found")
	errPkgIsGorootSrc    = errors.New("GOROOT/src is not an importable package")
	errPkgIsBuiltin      = errors.New(`"builtin" is a pseudo-package, not an importable package`)
)

// pathInModuleCache returns the import path of the directory dir,
// if dir is in the module cache copy of a module in our build list.
func pathInModuleCache(ld *Loader, ctx context.Context, dir string, rs *Requirements) string {
	tryMod := func(m module.Version) (string, bool) {
		if gover.IsToolchain(m.Path) {
			return "", false
		}
		var root string
		var err error
		if repl := Replacement(ld, m); repl.Path != "" && repl.Version == "" {
			root = repl.Path
			if !filepath.IsAbs(root) {
				root = filepath.Join(replaceRelativeTo(ld), root)
			}
		} else if repl.Path != "" {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Target a concrete standard-library package path (e.g. fmt, net/http) instead of GOROOT/src.
  2. In GOROOT-walking tools, skip the bare src directory and only process its children.

Example fix

// before
pkg, _ := importer.Default().Import("src")

// after
pkg, _ := importer.Default().Import("fmt")
Defensive patterns

Strategy: validation

Validate before calling

// Skip the bare GOROOT/src directory when walking GOROOT.
func skipGorootSrc(dir, goroot string) bool {
    return filepath.Clean(dir) == filepath.Join(goroot, "src")
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Importing or building the literal path `GOROOT/src` (or passing that directory to go list/build), typically via tooling that walks GOROOT and treats each directory as a package.

Common situations: Static-analysis tools, doc generators, or scripts that recurse over GOROOT and fail to skip the root src directory.

Related errors


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