go-delve/delve · error

failed to open file '%s': %w

Error message

failed to open file '%s': %w

What it means

The `breakpoints -save <file>` command writes all breakpoints to a file so they can be restored later. It uses os.Create on the given path; if the OS refuses (bad directory, permission denied, path is a directory, too many open files, etc.), the open failure is wrapped as 'failed to open file %s: %w' with the underlying OS error attached.

Source

Thrown at pkg/terminal/command.go:1715

				if i+1 >= len(argv) {
					return errors.New("missing filename after -save flag")
				}
				saveFile = argv[i+1]
				break argsLoop // Exit loop since we found -save and its argument
			}
		}
	}

	breakPoints, err := t.client.ListBreakpoints(showAll)
	if err != nil {
		return err
	}

	// If -save flag is provided, save breakpoints to file
	if saveFile != "" {
		file, err := os.Create(saveFile)
		if err != nil {
			return fmt.Errorf("failed to open file '%s': %w", saveFile, err)
		}
		defer file.Close()
		w := bufio.NewWriter(file)
		defer w.Flush()

		// Instead of storing the ID, we label the breakpoints to
		// reference them properly in future executions
		aliaser := func(bp *api.Breakpoint) string {
			if bp.Name == "" {
				return fmt.Sprintf("bp%d", bp.ID)
			}
			return bp.Name
		}

		for _, bp := range breakPoints {
			// We don't need to store these breakpoints
			if bp.ID < 0 {
				continue

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Verify the parent directory exists (mkdir -p) and the path is not a directory itself.
  2. Check write permissions on the target directory (ls -ld, chmod/chown as needed).
  3. Use an absolute, correctly spelled path; quote it if it contains spaces.
  4. If running in a container/CI, ensure the filesystem is writable and not full (df -h).

Example fix

// before
breakpoints -save ./missing-dir/bps.txt
// failed to open file './missing-dir/bps.txt': open ./missing-dir/bps.txt: no such file or directory

// after
mkdir -p ./missing-dir
breakpoints -save ./missing-dir/bps.txt
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight check before running: breakpoints -save <path>
func canCreate(path string) error {
    dir := filepath.Dir(path)
    if fi, err := os.Stat(dir); err != nil {
        return fmt.Errorf("directory %s missing: %w", dir, err)
    } else if !fi.IsDir() {
        return fmt.Errorf("%s is not a directory", dir)
    }
    if fi, err := os.Stat(path); err == nil && fi.IsDir() {
        return fmt.Errorf("%s is a directory", path)
    }
    f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644)
    if err != nil {
        return err
    }
    f.Close()
    return nil
}

Try / catch

if err := cmd.Execute("breakpoints -save " + path); err != nil {
    var pe *fs.PathError
    if errors.As(err, pe) || strings.Contains(err.Error(), "failed to open file") {
        fmt.Fprintf(os.Stderr, "cannot save breakpoints: %v\n", err) // wrapped os error is included
    }
}

Prevention

When it happens

Trigger: `breakpoints -save /path/file.txt` where /path does not exist, the user lacks write permission, the path names an existing directory, or the filesystem is read-only — os.Create returns an error and it is wrapped at command.go:1715.

Common situations: Typo in the target directory (e.g. ~/brekpoints.txt path); running dlv as a user without write access to the current directory; -save path pointing at a directory; read-only container filesystem; disk full or inode limits.

Related errors


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