goreleaser/goreleaser · error

pre hook failed: %w

Error message

pre hook failed: %w

What it means

The dockers_v2 pipe runs user-defined pre-build hooks (shell commands) before `docker buildx build`. This error wraps any failure returned by runHook for the `hooks.pre` list, aborting the image build. It indicates a pre hook command exited non-zero or could not run.

Source

Thrown at internal/pipe/docker/v2/docker.go:247

	}

	log.WithField("id", d.ID).
		WithField("images", strings.Join(da.images, "\n")).
		Info("creating images")

	wd, err := makeContext(d, contextArtifacts(ctx, d), da.dockerfile)
	if err != nil {
		return err
	}
	defer os.RemoveAll(wd)

	hookFields := tmpl.Fields{
		keyImages:     da.images,
		keyDockerfile: da.dockerfile,
		keyContextDir: wd,
	}
	if err := runHook(ctx, hookFields, d.Hooks.Pre); err != nil {
		return fmt.Errorf("pre hook failed: %w", err)
	}

	digest, err := doBuild(ctx, d, wd, da.args)
	if err != nil {
		return err
	}

	hookFields[keyDigest] = digest
	if err := runHook(ctx, hookFields, d.Hooks.Post); err != nil {
		return fmt.Errorf("post hook failed: %w", err)
	}

	log.WithField("id", d.ID).
		WithField("images", strings.Join(da.images, "\n")).
		WithField("digest", digest).
		Info("created images")

	for _, img := range da.images {

View on GitHub (pinned to f5edd73956)

Solutions

  1. Run the failing hook command manually with the same working directory to see its real error output.
  2. Fix or remove the offending `hooks.pre` entry in .goreleaser.yaml.
  3. Ensure any binaries/scripts the hook calls are installed and on PATH in the CI environment.
  4. Check the hook's templates ({{ .Images }}, {{ .Dockerfile }}, {{ .ContextDir }}) resolve correctly.

Example fix

// before (.goreleaser.yaml)
dockers_v2:
  - hooks:
      pre:
        - ./scripts/validate.sh
// after (ensure executable or use sh)
dockers_v2:
  - hooks:
      pre:
        - sh ./scripts/validate.sh
Defensive patterns

Strategy: validation

Validate before calling

// shell: pre-flight check that hook commands exist before running goreleaser
for cmd in $(yq '.dockers_v2[].hooks.pre[]' .goreleaser.yaml); do
  command -v "$(echo "$cmd" | awk '{print $1}')" >/dev/null || { echo "missing hook binary: $cmd"; exit 1; }
done

Try / catch

err := goreleaserRelease(ctx)
if err != nil && strings.Contains(err.Error(), "pre hook failed") {
    // surface the underlying hook output already logged by runHook
    return fmt.Errorf("docker pre hook failed; check hook command and PATH: %w", err)
}

Prevention

When it happens

Trigger: A `dockers_v2.hooks.pre` entry in .goreleaser.yaml returns a non-zero exit code, references a binary not on PATH, or its own template fails, during the docker build image step.

Common situations: Hook script missing execute permission, depending on tools only present locally but not in CI, using template fields (images/dockerfile/context dir) incorrectly, or a linter/formatter hook failing on generated files.

Related errors


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