kubernetes/kops · error
addon manifest %q did not have a spec
Error message
addon manifest %q did not have a spec
What it means
BootstrapChannelBuilder.Normalize assembles the channelsapi.Addons object listing every addon manifest in the channel. Before appending, it asserts each manifest's addonSpec is non-nil; a nil spec means the manifest was never properly built (its spec/hash pipeline never ran), so the channel would be incomplete and kOps fails with the addon's name in the message.
Source
Thrown at upup/pkg/fi/cloudup/bootstrapchannelbuilder/bootstrapchannel.go:60
_ fi.CloudupHasDependencies = (*BootstrapChannel)(nil)
)
func (a *BootstrapChannel) GetDependencies(tasks map[string]fi.CloudupTask) []fi.CloudupTask {
dependencies := make([]fi.CloudupTask, 0, len(a.addonManifests))
for _, manifest := range a.addonManifests {
dependencies = append(dependencies, manifest)
}
return dependencies
}
func (a *BootstrapChannel) Normalize(c *fi.CloudupContext) error {
addonsObject := &channelsapi.Addons{}
addonsObject.Kind = "Addons"
addonsObject.ObjectMeta.Name = "bootstrap"
for _, manifest := range a.addonManifests {
if manifest.addonSpec == nil {
return fmt.Errorf("addon manifest %q did not have a spec", fi.ValueOf(manifest.Name))
}
if manifest.addonSpec.ManifestHash == "" {
return fmt.Errorf("addon %q manifest hash was not populated", fi.ValueOf(manifest.addonSpec.Name))
}
addonsObject.Spec.Addons = append(addonsObject.Spec.Addons, manifest.addonSpec)
}
if err := addonsObject.Verify(); err != nil {
return err
}
addonsYAML, err := utils.YamlMarshal(addonsObject)
if err != nil {
return fmt.Errorf("error serializing addons yaml: %v", err)
}
a.Contents = fi.NewBytesResource(addonsYAML)
return nilView on GitHub (pinned to 4c8573c808)
Solutions
- Ensure every addon goes through the AddonManifest build helper so addonSpec is populated before BootstrapChannelBuilder.Normalize runs
- Check task ordering/registration: the per-manifest Normalize must execute before the channel's Normalize; verify task dependencies/wiring
- If you added a new addon recently, diff against an existing addon's builder code to spot the missing spec wiring
- Re-run kops update with --dry-run and check the full error context to identify the failing addon name
Example fix
// before
a.addonManifests = append(a.addonManifests, &AddonManifest{Name: fi.PtrTo("my-addon"), source: res})
// after
m := buildAddonManifest(b, "my-addon", spec, res)
a.addonManifests = append(a.addonManifests, m) // spec wired via builder Defensive patterns
Strategy: validation
Validate before calling
for _, m := range a.addonManifests {
if m.addonSpec == nil {
return fmt.Errorf("addon %s registered without spec; ensure AddonManifest.Normalize ran", fi.ValueOf(m.Name))
}
} Type guard
func manifestHasSpec(m *AddonManifest) bool { return m != nil && m.addonSpec != nil } Prevention
- Register addons only via buildAddonManifest so specs are always populated
- Verify task normalization ordering: per-manifest Normalize before channel Normalize
- Add a builder-level test that iterates all addons asserting non-nil specs
When it happens
Trigger: Normalize runs over a.addonManifests and encounters an entry whose addonSpec field is nil — typically an AddonManifest registered in the builder whose Normalize (addonmanifest.go) never ran or never populated the spec, or one built manually in tests without a spec.
Common situations: A new addon added to the channel list without going through the buildAddonManifest pipeline; ordering issue where BootstrapChannelBuilder.Normalize runs before the manifest tasks are normalized; hand-written AddonManifest in custom builds.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- addon spec is not configured for %q
- addon source is not configured for %q
- addon %q manifest hash was not populated
- error reading addon %q manifest: %v
- error rendering addon %q template: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/529b04f155f85c77.
Report an issue: GitHub.