go-delve/delve · warning
errBinaryInfoClose
errBinaryInfoClose
Error message
multiple errors closing executable files
What it means
errBinaryInfoClose is the sentinel Delve returns from BinaryInfo.Close when closing one or more internal image readers failed; the individual errors are aggregated and reported as 'multiple errors closing executable files'. It signals resource leaks (unclosed ELF/PE file handles) rather than corrupted debugging state.
Source
Thrown at pkg/proc/bininfo.go:1212
return &md
}
}
return nil
}
// typeToImage returns the image containing the give type.
func (bi *BinaryInfo) typeToImage(typ godwarf.Type) *Image {
return bi.Images[typ.Common().Index]
}
func (bi *BinaryInfo) runtimeTypeTypename() string {
if goversion.ProducerAfterOrEqual(bi.Producer(), 1, 21) {
return "internal/abi.Type"
}
return "runtime._type"
}
var errBinaryInfoClose = errors.New("multiple errors closing executable files")
// Close closes all internal readers.
func (bi *BinaryInfo) Close() error {
var errs []error
for _, image := range bi.Images {
if err := image.Close(); err != nil {
errs = append(errs, err)
}
}
switch len(errs) {
case 0:
return nil
case 1:
return errs[0]
default:
return errBinaryInfoClose
}
}View on GitHub (pinned to a23773e6c3)
Solutions
- Log the aggregated error but continue shutdown — it is usually non-fatal
- Avoid closing BinaryInfo more than once; tie Close to target-group teardown
- Check for binary replacement (rm/rename of the executable) while attached; re-attach after upgrade
- Inspect the wrapped individual errors to find which image failed to close
Example fix
// before
bi.Close() // error swallowed silently
// after
if err := bi.Close(); err != nil {
if errors.Is(err, errBinaryInfoClose) {
log.Printf("warning: leaked executable file handles: %v", err)
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check: file handles for the images are still valid
for _, p := range imagePaths {
if _, err := os.Stat(p); err != nil {
log.Printf("executable file changed/unlinked: %s", p)
}
} Try / catch
if err := bi.Close(); err != nil {
if errors.Is(err, errBinaryInfoClose) {
log.Printf("non-fatal: %v", err) // log and continue teardown
}
} Prevention
- Close BinaryInfo exactly once during teardown
- Don't delete/replace the executable while attached
- Treat this as a warning; don't abort detach because of it
When it happens
Trigger: Calling BinaryInfo.Close() (directly or via TargetGroup/detach cleanup) after the underlying image files were already closed, deleted, or failed to open in a partially-initialized state.
Common situations: Detaching from processes whose executable was deleted/upgraded on disk (common with atomic binary replacement); closing BinaryInfo twice; macOS code-signed binaries reopened between fork-exec steps failing re-open.
Related errors
- hardware breakpoints exhausted
- break on read only not supported
- ErrCouldNotDetermineRelocation
- could not decode first frame
- unable to find function context
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/815105669aea45c4.
Report an issue: GitHub.