{"record":{"id":"f31d67a2ec9c2cd9","repo":"hashicorp/packer","slug":"prepare-must-be-called-first","errorCode":null,"errorMessage":"Prepare must be called first","messagePattern":"Prepare must be called first","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packer/build.go","lineNumber":199,"sourceCode":"\tfor _, k := range generatedVars {\n\t\tgeneratedPlaceholderMap[k] = fmt.Sprintf(\"Build_%s. \"+\n\t\t\tpackerbuilderdata.PlaceholderMsg, k)\n\t}\n\n\treturn generatedPlaceholderMap\n}\n\n// SetGeneratedVars stores the builder-generated variables from the initial\n// builder preparation so late-injected provisioners can reuse them without\n// invoking Builder.Prepare again.\nfunc (b *CoreBuild) SetGeneratedVars(generatedVars []string) {\n\tb.generatedVars = append([]string(nil), generatedVars...)\n}\n\n// PrepareProvisioners prepares provisioners injected after the build itself has already been prepared.\nfunc (b *CoreBuild) PrepareProvisioners(provisioners ...CoreBuildProvisioner) error {\n\tif !b.prepareCalled {\n\t\treturn fmt.Errorf(\"Prepare must be called first\")\n\t}\n\n\tpackerConfig := b.packerConfig()\n\treturn b.prepareProvisioners(provisioners, packerConfig, b.generatedVars)\n}\n\n// Prepare prepares the build by doing some initialization for the builder\n// and any hooks. This _must_ be called prior to Run. The parameter is the\n// overrides for the variables within the template (if any).\nfunc (b *CoreBuild) Prepare() (warn []string, err error) {\n\t// For HCL2 templates, the builder and hooks are initialized when the\n\t// template is parsed. Calling Prepare(...) is not necessary\n\tif b.Prepared {\n\t\tb.prepareCalled = true\n\t\treturn\n\t}\n\n\tb.l.Lock()","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/packer/build.go#L181-L217","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nbuild.PrepareProvisioners(pps...)\n// after\nif _, err := build.Prepare(); err != nil {\n    return err\n}\nif err := build.PrepareProvisioners(pps...); err != nil {\n    return err\n}","handlingStrategy":"validation","validationCode":"func prepareThenInject(b *packer.CoreBuild, pps ...packer.CoreBuildProvisioner) error {\n    if _, err := b.Prepare(); err != nil {\n        return fmt.Errorf(\"build prepare failed: %w\", err)\n    }\n    return b.PrepareProvisioners(pps...)\n}","typeGuard":null,"tryCatchPattern":"if err := b.PrepareProvisioners(pps...); err != nil {\n    if err.Error() == \"Prepare must be called first\" {\n        return fmt.Errorf(\"lifecycle bug: call Prepare() before PrepareProvisioners(): %w\", err)\n    }\n    return err\n}","preventionTips":["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"],"tags":["lifecycle","build","api-misuse"],"backgroundTag":"prepare-must-be-called-first","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}