golang/go · error
%s: missing .go_export section
Error message
%s: missing .go_export section
What it means
After elf.Open succeeds on a gccgo shared library, the code looks for the .go_export section, which gccgo writes to record embedded package metadata. If the section is nil, the file is ELF but not a gccgo-produced shared library, and readpkglist aborts via base.Fatal.
Source
Thrown at src/cmd/go/internal/work/action.go:409
b.objdirSeq++
return str.WithFilePathSeparator(filepath.Join(b.WorkDir, fmt.Sprintf("b%03d", b.objdirSeq)))
}
// readpkglist returns the list of packages that were built into the shared library
// at shlibpath. For the native toolchain this list is stored, newline separated, in
// an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the
// .go_export section.
func readpkglist(s *modload.Loader, shlibpath string) (pkgs []*load.Package) {
var stk load.ImportStack
if cfg.BuildToolchainName == "gccgo" {
f, err := elf.Open(shlibpath)
if err != nil {
base.Fatal(fmt.Errorf("failed to open shared library: %v", err))
}
defer f.Close()
sect := f.Section(".go_export")
if sect == nil {
base.Fatal(fmt.Errorf("%s: missing .go_export section", shlibpath))
}
data, err := sect.Data()
if err != nil {
base.Fatal(fmt.Errorf("%s: failed to read .go_export section: %v", shlibpath, err))
}
pkgpath := []byte("pkgpath ")
for _, line := range bytes.Split(data, []byte{'\n'}) {
if path, found := bytes.CutPrefix(line, pkgpath); found {
path = bytes.TrimSuffix(path, []byte{';'})
pkgs = append(pkgs, load.LoadPackageWithFlags(s, string(path), base.Cwd(), &stk, nil, 0))
}
}
} else {
pkglistbytes, err := buildid.ReadELFNote(shlibpath, "Go\x00\x00", 1)
if err != nil {
base.Fatalf("readELFNote failed: %v", err)
}
scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes))View on GitHub (pinned to b6b368adc5)
Solutions
- Run 'go clean -cache' to remove cross-toolchain artifacts.
- Rebuild all shared libraries with the same gccgo toolchain you're building with now.
- Confirm with 'readelf -S <path>' whether .go_export is present.
- Avoid mixing -buildmode=shared outputs between gc and gccgo in the same GOCACHE.
Example fix
// before: cache has gc-produced .so but build is gccgo $ go build -compiler=gccgo -buildmode=shared -linkshared ./... // error: libstd.so: missing .go_export section // after $ go clean -cache $ go build -compiler=gccgo -buildmode=shared std $ go build -compiler=gccgo -linkshared ./...
Defensive patterns
Strategy: validation
Validate before calling
// Confirm an ELF is gccgo-produced by checking for .go_export.
func isGccgoShlib(path string) bool {
f, err := elf.Open(path)
if err != nil { return false }
defer f.Close()
return f.Section(".go_export") != nil
} Prevention
- Never mix gc and gccgo outputs in the same GOCACHE.
- Run 'go clean -cache' after switching compilers.
- Verify shared libraries with 'readelf -S' before referencing them.
When it happens
Trigger: A non-gccgo ELF shared library (e.g. one produced by the gc compiler's -buildmode=shared, or a plain C .so) is referenced where a gccgo .so is expected. Cache corruption mixing toolchains can also do this.
Common situations: Switching between gc and gccgo without 'go clean -cache'; pointing -pkgdir at a tree built by the other compiler; a hand-written makefile that mixes toolchains.
Related errors
- failed to open shared library: %v
- %s: failed to read .go_export section: %v
- too long
- file is empty
- entry file incomplete
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/a1f6cff7bc841a47.
Report an issue: GitHub.