golang/go · error

failed to open shared library: %v

Error message

failed to open shared library: %v

What it means

readpkglist calls elf.Open on a gccgo-built shared library path to extract its embedded package list. If elf.Open returns an error (file missing, not ELF, truncated), the go command calls base.Fatal with this wrapped error, terminating the build.

Source

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

//
// NewObjdir must be called only from a single goroutine at a time,
// so it is safe to call during action graph construction, but it must not
// be called during action graph execution.
func (b *Builder) NewObjdir() string {
	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 {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Run 'go clean -cache' to discard stale shared-library references.
  2. Rebuild the shared library with -buildmode=shared so its path is fresh.
  3. Verify the shlibpath exists and is readable: 'file <path>' should report ELF.
  4. Ensure GOFLAGS/-pkgdir isn't pointing at a stale output tree.

Example fix

// before: stale cache references a deleted .so
$ go build -buildmode=shared -linkshared ./...
// error: failed to open shared library: open /tmp/.../libstd.so: no such file

// after
$ go clean -cache
$ go build -buildmode=shared -o libstd.so std
$ go build -linkshared ./...
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify a gccgo shared library is a readable ELF before referencing it.
func checkShlib(path string) error {
    f, err := elf.Open(path)
    if err != nil { return fmt.Errorf("%s: not a readable ELF", path) }
    defer f.Close()
    return nil
}

Try / catch

// Treat a missing/corrupt shlib as a cache reset, not a fatal error.
if _, err := readpkglist(loader, path); err != nil {
    log.Printf("shlib unreadable, resetting cache: %v", err)
    _ = os.RemoveAll(cfg.GOCACHE)
    // rebuild shared libs and retry
}

Prevention

When it happens

Trigger: Building with -buildmode=shared under gccgo, or consuming a prior -shared gccgo artifact, where the recorded shlib path is unreadable, deleted, or not an ELF file. Also triggered by a stale build cache pointing at a removed .so.

Common situations: Build cache corruption; the .so was garbage-collected (GOCACHE cleanup) but its cache entry remained; cross-mounted filesystem where the .so isn't visible; a non-gccgo .so being interpreted as one.

Related errors


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