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

  1. Call b.Prepare() (and confirm it returns no error) before calling PrepareProvisioners
  2. Check for and handle errors from Prepare — a failed Prepare does not set prepareCalled
  3. If injecting provisioners post-prepare, ensure SetGeneratedVars/Prepare ordering matches the documented lifecycle
  4. 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

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


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/f31d67a2ec9c2cd9. Report an issue: GitHub.