hashicorp/packer · error
Prepare must be called first
Error message
Prepare must be called first
What it means
CoreBuild.PrepareProvisioners injects provisioners into a build that was prepared earlier, but it requires that CoreBuild.Prepare was already invoked (b.prepareCalled set). If called on a build that was never prepared, it returns "Prepare must be called first". It is an API-ordering/usage error within the packer build lifecycle.
Source
Thrown at packer/build.go:199
for _, k := range generatedVars {
generatedPlaceholderMap[k] = fmt.Sprintf("Build_%s. "+
packerbuilderdata.PlaceholderMsg, k)
}
return generatedPlaceholderMap
}
// SetGeneratedVars stores the builder-generated variables from the initial
// builder preparation so late-injected provisioners can reuse them without
// invoking Builder.Prepare again.
func (b *CoreBuild) SetGeneratedVars(generatedVars []string) {
b.generatedVars = append([]string(nil), generatedVars...)
}
// PrepareProvisioners prepares provisioners injected after the build itself has already been prepared.
func (b *CoreBuild) PrepareProvisioners(provisioners ...CoreBuildProvisioner) error {
if !b.prepareCalled {
return fmt.Errorf("Prepare must be called first")
}
packerConfig := b.packerConfig()
return b.prepareProvisioners(provisioners, packerConfig, b.generatedVars)
}
// Prepare prepares the build by doing some initialization for the builder
// and any hooks. This _must_ be called prior to Run. The parameter is the
// overrides for the variables within the template (if any).
func (b *CoreBuild) Prepare() (warn []string, err error) {
// For HCL2 templates, the builder and hooks are initialized when the
// template is parsed. Calling Prepare(...) is not necessary
if b.Prepared {
b.prepareCalled = true
return
}
b.l.Lock()View on GitHub (pinned to eb36e3c3e4)
Solutions
- Call b.Prepare() (and confirm it returns no error) before calling PrepareProvisioners
- Check for and handle errors from Prepare — a failed Prepare does not set prepareCalled
- If injecting provisioners post-prepare, ensure SetGeneratedVars/Prepare ordering matches the documented lifecycle
- Restructure code so provisioner injection happens inside or after the normal Prepare flow
Example fix
// before
build.PrepareProvisioners(pps...)
// after
if _, err := build.Prepare(); err != nil {
return err
}
if err := build.PrepareProvisioners(pps...); err != nil {
return err
} Defensive patterns
Strategy: validation
Validate before calling
func prepareThenInject(b *packer.CoreBuild, pps ...packer.CoreBuildProvisioner) error {
if _, err := b.Prepare(); err != nil {
return fmt.Errorf("build prepare failed: %w", err)
}
return b.PrepareProvisioners(pps...)
} Try / catch
if err := b.PrepareProvisioners(pps...); err != nil {
if err.Error() == "Prepare must be called first" {
return fmt.Errorf("lifecycle bug: call Prepare() before PrepareProvisioners(): %w", err)
}
return err
} Prevention
- Enforce the Prepare→Run ordering in wrapper code rather than calling CoreBuild methods ad hoc
- Handle errors from Prepare; a failed Prepare leaves prepareCalled unset
- Add a unit test mirroring TestBuild_PrepareProvisioners_RequiresPrepare for any custom build orchestration
When it happens
Trigger: Calling CoreBuild.PrepareProvisioners(provisioners...) directly on a CoreBuild without a prior successful call to Prepare() — the unit test TestBuild_PrepareProvisioners_RequiresPrepare exercises exactly this path.
Common situations: Tool authors programmatically building packer CoreBuild objects who inject provisioners before preparing the build; test harnesses constructing CoreBuild manually and skipping Prepare; calling PrepareProvisioners after Prepare returned an error and left prepareCalled unset.
Related errors
- the iteration %s is revoked and can not be used on Packer bu
- the iteration associated with the channel %s is revoked and
- something went wrong retrieving the build %s from bucket %s
- NewBuildFromCloudPackerBuild: %w
- Post-processor failed: %s
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/f31d67a2ec9c2cd9.
Report an issue: GitHub.