hashicorp/packer · error

hash artifact %q: %w

Error message

hash artifact %q: %w

What it means

verifyArtifactSubject hashes the artifact file at artifactPath with sha256File before comparing it against provenance subjects. If hashing fails (file cannot be opened, read error during io.Copy), the error is wrapped with `hash artifact %q: %w` preserving the original os/io error.

Source

Thrown at internal/attestation/verify.go:386

	bundleSignature := bundleEnvelope.Signature()
	for i, envelopeSignature := range envelope.Signatures {
		signature, err := DecodeEnvelopeSignature(envelopeSignature)
		if err != nil {
			return fmt.Errorf("decode attestation envelope signature %d: %w", i, err)
		}

		if bytes.Equal(bundleSignature, signature) {
			return nil
		}
	}

	return fmt.Errorf("sigstore bundle signature does not match any attestation signature")
}

func verifyArtifactSubject(subjects []internalprovenance.Subject, artifactPath string) error {
	digest, err := sha256File(artifactPath)
	if err != nil {
		return fmt.Errorf("hash artifact %q: %w", artifactPath, err)
	}

	artifactName := filepath.Base(artifactPath)
	for _, subject := range subjects {
		if subject.Name == artifactName && strings.EqualFold(subject.Digest["sha256"], digest) {
			return nil
		}
	}

	return fmt.Errorf("attestation subject does not match artifact %q", artifactPath)
}

func sha256File(path string) (string, error) {
	file, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer func() { _ = file.Close() }()

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Check the artifact file exists at the exact path and that the process has read permission (ls -l, or os.Stat before verification)
  2. Run the verification from the correct working directory or pass an absolute path to the artifact
  3. Download/produce the artifact before running policy verification
  4. Inspect the wrapped underlying error (os.PathError) for the precise open/read failure

Example fix

// before: relative path resolved from wrong cwd
verifyPolicy(policy, "bin/app")
// after: absolute path plus existence check
if _, err := os.Stat(artifactPath); err != nil { return err }
verifyPolicy(policy, "/abs/path/to/bin/app")
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(artifactPath); err != nil {
    return fmt.Errorf("artifact not readable: %w", err)
}

Try / catch

if err := verifyPolicy(policy, path); err != nil {
    if strings.HasPrefix(err.Error(), "hash artifact") {
        return fmt.Errorf("cannot read artifact %s: %w", path, err)
    }
    return err
}

Prevention

When it happens

Trigger: verifyPolicy calls verifyArtifactSubject with an artifactPath that does not exist, is a directory, has insufficient read permissions, or is unreadable mid-read (I/O error while streaming into the hasher).

Common situations: Typoed or relative artifact path resolved from a different working directory than the test/verification run; artifact deleted or not downloaded before verification; running the verifier as a user lacking read permission on the artifact.

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 hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/20dfc76b322b4b94. Report an issue: GitHub.