hashicorp/packer · error
artifact is nil
Error message
artifact is nil
What it means
deriveSubjects in internal/provenance/subject.go refuses to operate on a nil packersdk.Artifact. Subject derivation (SHA-256 digests of artifact files, or a digest over the builder identity) requires a concrete artifact, so a nil input is rejected up front with a plain error. It is a defensive guard: callers passing a nil artifact have lost the build output somewhere upstream.
Source
Thrown at internal/provenance/subject.go:36
type DigestSet map[string]string
type Subject struct {
Name string `json:"name"`
Digest DigestSet `json:"digest"`
}
func DeriveSubjects(artifact packersdk.Artifact) ([]Subject, error) {
return deriveSubjects(artifact)
}
func DeriveIdentityRecord(artifact packersdk.Artifact) (map[string]interface{}, error) {
return deriveIdentityRecord(artifact)
}
func deriveSubjects(artifact packersdk.Artifact) ([]Subject, error) {
if artifact == nil {
return nil, fmt.Errorf("artifact is nil")
}
files := artifact.Files()
if len(files) > 0 {
subjects := make([]Subject, 0, len(files))
for _, file := range files {
digest, err := sha256File(file)
if err != nil {
return nil, fmt.Errorf("hash %q: %w", file, err)
}
subjects = append(subjects, Subject{
Name: filepath.Base(file),
Digest: DigestSet{
"sha256": digest,
},
})
}View on GitHub (pinned to eb36e3c3e4)
Solutions
- Check artifact != nil before calling DeriveSubjects / DeriveIdentityRecord
- Verify the upstream builder actually produced an artifact (check build errors and artifact list length)
- In loops over artifacts, skip nil entries explicitly
- Wrap the call in error handling and degrade gracefully (skip provenance for that artifact)
Example fix
// before
subjects, err := provenance.DeriveSubjects(artifact)
// after
if artifact == nil {
return nil // no artifact produced; skip provenance
}
subjects, err := provenance.DeriveSubjects(artifact) Defensive patterns
Strategy: validation
Validate before calling
if artifact == nil {
return nil, fmt.Errorf("no artifact produced by build; skipping provenance")
}
_ = artifact // safe to pass Type guard
func isNilArtifact(a packersdk.Artifact) bool { return a == null || reflect.ValueOf(a).IsNil() } Try / catch
subjects, err := provenance.DeriveSubjects(artifact)
if err != nil {
if err.Error() == "artifact is nil" { log.Warn("no artifact; skipping subjects"); return nil }
return err
} Prevention
- Nil-check artifacts immediately after build completion
- Skip provenance steps when a build yields zero artifacts
- Treat nil artifact as 'nothing to attest', not a crash
When it happens
Trigger: Calling DeriveSubjects(nil) or DeriveIdentityRecord(nil), or passing an artifact variable that a builder/plugin returned as nil (e.g. a build with no artifact) into those functions.
Common situations: A builder produced no artifact (failed or imageless build) and post-processing/provenance code still runs; iterating over multiple artifacts where one entry is nil; wiring a post-processor where artifact retrieval was skipped on error.
Related errors
- attestation subject does not match artifact %q
- hash %q: %w
- marshal artifact identity: %w
- signing_mode %q does not support Sigstore bundle emission
- decode envelope payload: %w
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/13042bdd21a63451.
Report an issue: GitHub.