goreleaser/goreleaser · error

could not open %q: %w

Error message

could not open %q: %w

What it means

Raised when os.Open on the `.bkp` backup of the archive fails inside appendExtraFilesToArchive. After a successful backup, the pipe re-opens the backup as the read source for archive.Copy; failure here means the backup file is unreadable even though it was just written.

Source

Thrown at internal/pipe/sourcearchive/source.go:91

		Path: path,
		Extra: map[string]any{
			artifact.ExtraFormat: format,
		},
	})
	return err
}

func appendExtraFilesToArchive(ctx *context.Context, prefix, name, format string) error {
	oldPath := name + ".bkp"
	if err := gio.Copy(name, oldPath); err != nil {
		return fmt.Errorf("failed make a backup of %q: %w", name, err)
	}

	// i could spend a lot of time trying to figure out how to append to a tar,
	// tgz and zip file... but... this seems easy enough :)
	of, err := os.Open(oldPath)
	if err != nil {
		return fmt.Errorf("could not open %q: %w", oldPath, err)
	}
	defer of.Close()

	af, err := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC, 0o644)
	if err != nil {
		return fmt.Errorf("could not open archive: %w", err)
	}
	defer af.Close()

	arch, err := archive.Copy(of, af, format)
	if err != nil {
		return err
	}

	files, err := archivefiles.Eval(tmpl.New(ctx), ctx.Config.Source.Files)
	if err != nil {
		return err
	}

View on GitHub (pinned to f5edd73956)

Solutions

  1. Re-run the release in a clean dist directory (goreleaser release --clean or rm -rf dist).
  2. Avoid concurrent goreleaser runs sharing the same dist folder.
  3. Check filesystem permissions and any file watchers/AV that could remove the .bkp file.

Example fix

// before (shared dist between parallel jobs)
- run: goreleaser build --snapshot &
// after
- run: goreleaser build --snapshot --clean # unique dist per job
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := os.Stat(oldPath); err != nil { return fmt.Errorf("backup vanished: %w", err) }

Try / catch

if err := appendExtraFilesToArchive(ctx, prefix, name, format); err != nil {
    if strings.Contains(err.Error(), "could not open") {
        // clean dist and re-run; check for concurrent jobs / AV deletion
    }
}

Prevention

When it happens

Trigger: os.Open(oldPath) returns an error right after gio.Copy succeeded — rare race, permission change, or filesystem issue on the `<name>.bkp` file.

Common situations: Antivirus/CI cleaners deleting temp files between steps, concurrent builds writing the same dist paths, or unusual umask/permissions in containers.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of goreleaser/goreleaser@f5edd73956 (2026-09-05). Data as JSON: /api/errors/3f3a0e751e0a9941. Report an issue: GitHub.