golang/go · error

%s: failed to read .go_export section: %v

Error message

%s: failed to read .go_export section: %v

What it means

elf.Open succeeded and the .go_export section exists, but sect.Data() returned an I/O error reading the section's bytes. readpkglist wraps the underlying error and calls base.Fatal. This is a low-level read failure on an otherwise well-formed ELF.

Source

Thrown at src/cmd/go/internal/work/action.go:413

// 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))
		for scanner.Scan() {
			t := scanner.Text()
			pkgs = append(pkgs, load.LoadPackageWithFlags(s, t, base.Cwd(), &stk, nil, 0))
		}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Run 'go clean -cache' and rebuild the shared library from scratch.
  2. Check disk space and dmesg for I/O errors on the underlying device.
  3. Move GOCACHE off network filesystems to a local fast SSD.
  4. Serialize builds that share a -pkgdir to avoid torn writes.

Example fix

// before: torn .so on full disk
$ go build -buildmode=shared -linkshared ./...
// error: libstd.so: failed to read .go_export section: read .go_export: input/output error

// after
$ df -h /tmp          # free space
$ go clean -cache
$ go build -buildmode=shared std && go build -linkshared ./...
Defensive patterns

Strategy: retry

Try / catch

// Treat a torn .go_export read as transient: clean and retry.
err := buildShared()
if err != nil && strings.Contains(err.Error(), "failed to read .go_export") {
    goCleanCache()
    err = buildShared()
}

Prevention

When it happens

Trigger: The shared library is truncated mid-section, lives on a failing disk/NFS mount, or was concurrently rewritten while being read. A partial write of the .so (build interrupted) is the most common cause.

Common situations: Build killed while writing the .so; storage full; concurrent 'go build' invocations writing the same -pkgdir; NFS caching stale pages.

Related errors


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