go-delve/delve · error

can't open separate debug file:

Error message

can't open separate debug file: 

What it means

When the executable itself lacks debug info, Delve follows the GNU debuglink/build-id to a separate debug file and tries to open it with os.OpenFile. If that open fails (the path exists per debuglink but is unreadable/absent), it returns 'can't open separate debug file: <reason>'. The message deliberately embeds the OS error.

Source

Thrown at pkg/proc/bininfo.go:1687

			notify = func(s string) {
				bi.eventsFn(&Event{
					Kind: EventBinaryInfoDownload,
					BinaryInfoDownloadEventDetails: &BinaryInfoDownloadEventDetails{
						ImagePath: image.Path,
						Progress:  s,
					},
				})
			}
		}
		debugFilePath, err = debuginfod.GetDebuginfo(bi.downloadsCtx, notify, image.BuildID)
		if err != nil {
			return nil, nil, ErrNoDebugInfoFound
		}
	}

	sepFile, err := os.OpenFile(debugFilePath, 0, os.ModePerm)
	if err != nil {
		return nil, nil, errors.New("can't open separate debug file: " + err.Error())
	}

	elfFile, err := elf.NewFile(sepFile)
	if err != nil {
		sepFile.Close()
		return nil, nil, fmt.Errorf("can't open separate debug file %q: %v", debugFilePath, err.Error())
	}

	if !supportedLinuxArch[elfFile.Machine] {
		sepFile.Close()
		return nil, nil, fmt.Errorf("can't open separate debug file %q: %v", debugFilePath, &ErrUnsupportedArch{os: "linux", cpuArch: elfFile.Machine})
	}

	return sepFile, elfFile, nil
}

// loadBinaryInfoElf specifically loads information from an ELF binary.
func loadBinaryInfoElf(bi *BinaryInfo, image *Image, path string, addr uint64, wg *sync.WaitGroup) error {

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Install the matching debug symbols package so the debuglink/build-id target exists
  2. Check permissions on the debug file path shown in the wrapped OS error (chmod a+r)
  3. Verify the debuglink path: the file must be at <dir>/<link>, <dir>/.debug/<link>, or /usr/lib/debug/<dir>/<link>
  4. Copy the unstripped binary or .debug file from the build machine to the same relative path

Example fix

// before
$ ls /usr/lib/debug/usr/bin/app
ls: cannot access ... No such file or directory
// after
$ apt-get install app-dbg   # or copy app.debug next to the binary
$ chmod a+r /usr/lib/debug/usr/bin/app
Defensive patterns

Strategy: validation

Validate before calling

func debugFileResolves(binaryPath, debugLink string) error {
    for _, p := range []string{
        filepath.Join(filepath.Dir(binaryPath), debugLink),
        filepath.Join(filepath.Dir(binaryPath), ".debug", debugLink),
        filepath.Join("/usr/lib/debug", filepath.Dir(binaryPath), debugLink)} {
        if _, err := os.Stat(p); err == nil { return nil }
    }
    return fmt.Errorf("debug file %s not found for %s", debugLink, binaryPath)
}

Try / catch

if _, _, err := loadSeparateDebugFile(...); err != nil {
    if strings.HasPrefix(err.Error(), "can't open separate debug file:") {
        // check wrapped OS error: ENOENT -> install dbgsym; EACCES -> fix permissions
    }
}

Prevention

When it happens

Trigger: debuglink points to a file path that doesn't exist or has bad permissions; os.OpenFile(debugFilePath, 0, os.ModePerm) fails with ENOENT/EACCES during loadBinaryInfoElf's separate-debug-file resolution.

Common situations: Debug packages not installed on the machine; /usr/lib/debug trees missing after container image slimming; wrong permissions on the .debug file; stale debuglink after the binary was copied to another host.

Related errors


AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31). Data as JSON: /api/errors/5a2a566583334b32. Report an issue: GitHub.