ipfs/kubo · warning

opening binary

Error message

opening binary %q: %w

What it means

After resolving the path (via /proc/<pid>/exe on Linux or os.Executable elsewhere), binary() opens the executable with os.Open(path) to copy it into the archive. This error means the resolved binary path exists as a concept but could not be opened for reading, wrapped with the actual path for diagnosis.

Solutions

  1. Check the wrapped path and verify it exists and is readable by the process user (ls -l, test -r)
  2. Relax SELinux/AppArmor rules or run the diagnostics collection as a user that can read the binary
  3. Keep the executable file present while the process runs (do not delete-on-upgrade before profiling)
  4. Skip the binary-embedding collector gracefully if unreadable — treat it as optional in your profile set

Example fix

// before
err := WriteProfiles(ctx, p) // fails hard: opening binary "/app/ipfs": permission denied
// after
if _, serr := os.Stat(binPath); serr == nil {
    if _, oerr := os.Open(binPath); oerr == nil {
        err := WriteProfiles(ctx, p)
    }
} // or drop the 'binary' collector from the profile list when unreadable
Defensive patterns

Strategy: validation

Validate before calling

path := binPathFor(runtime.GOOS) // /proc/self/exe or os.Executable()
if fi, err := os.Open(path); err != nil {
    log.Printf("binary %s unreadable, skip embedding: %v", path, err)
} else {
    fi.Close()
}

Try / catch

if err := WriteProfiles(ctx, p); err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) && strings.HasPrefix(err.Error(), "opening binary") {
        log.Printf("cannot read binary %s (%v); disable the binary collector", pe.Path, pe.Err)
    }
    return err
}

Prevention

When it happens

Trigger: os.Open(path) fails: the executable file was deleted after path resolution (dangling path on non-Linux), the process lacks read permission on the binary, /proc/<pid>/exe resolution failed on Linux (e.g. permission checks on deleted binaries), or a security module (SELinux/AppArmor) blocks reading the executable.

Common situations: Binaries run with dropped privileges that can no longer read their own image; hardened containers with noexec/no-read policies; deleted-but-running executables on non-Linux systems; SELinux enforcing profiles denying /proc/pid/exe reads.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/315f4821938f1747. Report an issue: GitHub.

Appendix: source

Thrown at profile/profile.go:237

}

func binary(ctx context.Context, _ Options, w io.Writer) error {
	var (
		path string
		err  error
	)
	if goos == "linux" {
		pid := os.Getpid()
		path = fmt.Sprintf("/proc/%d/exe", pid)
	} else {
		path, err = os.Executable()
		if err != nil {
			return fmt.Errorf("finding binary path: %w", err)
		}
	}
	fi, err := os.Open(path)
	if err != nil {
		return fmt.Errorf("opening binary %q: %w", path, err)
	}
	_, err = io.Copy(w, fi)
	_ = fi.Close()
	if err != nil {
		return fmt.Errorf("copying binary %q: %w", path, err)
	}
	return nil
}

func mutexProfile(ctx context.Context, opts Options, w io.Writer) error {
	prev := runtime.SetMutexProfileFraction(opts.MutexProfileFraction)
	defer runtime.SetMutexProfileFraction(prev)
	err := waitOrCancel(ctx, opts.ProfileDuration)
	if err != nil {
		return err
	}
	return pprof.Lookup("mutex").WriteTo(w, 2)
}

View on GitHub (pinned to 329838acdf)