ipfs/kubo · warning
opening binary %q: %w
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.
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)
Solutions
- Check the wrapped path and verify it exists and is readable by the process user (ls -l, test -r)
- Relax SELinux/AppArmor rules or run the diagnostics collection as a user that can read the binary
- Keep the executable file present while the process runs (do not delete-on-upgrade before profiling)
- 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
- Run diagnostics as a user that can read the executable image
- Audit SELinux/AppArmor/container policies for /proc/<pid>/exe reads if profiling on Linux
- Keep the binary on disk for the process lifetime; do not delete-on-upgrade
- Make binary embedding a skippable step in profile bundles
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
- copying binary %q: %w
- error creating output file '%s': %w
- serveHTTPApi: SetAPIAddr() failed: %w
- %s is not writeable by the current user
- unexpected error while checking writeablility of repo root:
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/315f4821938f1747.
Report an issue: GitHub.