{"record":{"id":"1783ad00eae67afc","repo":"kubernetes/kops","slug":"addon-source-is-not-configured-for-q","errorCode":null,"errorMessage":"addon source is not configured for %q","messagePattern":"addon source is not configured for %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/bootstrapchannelbuilder/addonmanifest.go","lineNumber":81,"sourceCode":"// the task graph see fully realized state. Intentionally pessimistic: addon rendering is fast\n// enough that over-depending is not worth the footgun of under-declaring.\nfunc (a *AddonManifest) GetDependencies(tasks map[string]fi.CloudupTask) []fi.CloudupTask {\n\tdependencies := make([]fi.CloudupTask, 0, len(tasks))\n\tfor _, task := range tasks {\n\t\tif isAddonTask(task) {\n\t\t\tcontinue\n\t\t}\n\t\tdependencies = append(dependencies, task)\n\t}\n\treturn dependencies\n}\n\nfunc (a *AddonManifest) Normalize(c *fi.CloudupContext) error {\n\tif a.addonSpec == nil {\n\t\treturn fmt.Errorf(\"addon spec is not configured for %q\", fi.ValueOf(a.Name))\n\t}\n\tif a.source == nil {\n\t\treturn fmt.Errorf(\"addon source is not configured for %q\", fi.ValueOf(a.Name))\n\t}\n\n\tmanifestBytes, err := fi.ResourceAsBytes(a.source)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error reading addon %q manifest: %v\", fi.ValueOf(a.Name), err)\n\t}\n\n\tif !a.skipRender && a.addonRenderer != nil {\n\t\tmanifestBytes, err = a.addonRenderer.RenderTemplate(fi.ValueOf(a.Location), manifestBytes, tasksVisibleToAddons(c.AllTasks()))\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error rendering addon %q template: %w\", fi.ValueOf(a.Name), err)\n\t\t}\n\t}\n\n\tif !a.skipRemap {\n\t\tmanifestBytes, err = addonmanifests.RemapAddonManifest(a.addonSpec, a.modelContext, a.assetBuilder, manifestBytes, a.serviceAccounts)\n\t\tif err != nil {\n\t\t\tklog.Infof(\"invalid manifest: %s\", string(manifestBytes))","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/bootstrapchannelbuilder/addonmanifest.go#L63-L99","documentation":"AddonManifest.Normalize requires a source resource (the raw or template manifest bytes) before it can read the addon manifest. If a.source is nil there is nothing to read, render, hash, or attach to the channel, so normalization aborts with this message identifying the addon by name.","triggerScenarios":"Normalize is called (directly or via task normalization; covered by TestAddonManifestNormalizeSkipsRenderForRawSources and TestAddonManifestNormalizeRendersTemplateSources) with addonSpec set but a.source never assigned — the builder step that maps the channel's manifest location into a fi.Resource was skipped or failed silently.","commonSituations":"A bootstrap channel builder branch that returns an AddonManifest without calling the helper that sets source from the addon's manifest path; a refactor that removed the fi.NewBytesResource/URL resource wiring; a test constructing AddonManifest manually with only Name and addonSpec.","solutions":["Locate the AddonManifest construction for the named addon in bootstrapchannelbuilder and assign source (e.g. via fi.NewBytesResource or the channel's manifest resource)","Use the existing buildAddonManifest helper instead of building AddonManifest directly so source is always wired","In tests, set source: fi.NewBytesResource([]byte(...)) before calling Normalize","Re-run go test ./upup/pkg/fi/cloudup/bootstrapchannelbuilder/... to confirm which addon is affected"],"exampleFix":"// before\nm := &AddonManifest{Name: fi.PtrTo(\"kube-dns\"), addonSpec: spec}\n// after\nm := &AddonManifest{Name: fi.PtrTo(\"kube-dns\"), addonSpec: spec, source: fi.NewBytesResource(manifestBytes)}","handlingStrategy":"validation","validationCode":"if m.source == nil {\n    return fmt.Errorf(\"addon %s: source resource must be set before Normalize\", fi.ValueOf(m.Name))\n}","typeGuard":"func (a *AddonManifest) HasSource() bool { return a.source != nil }","tryCatchPattern":null,"preventionTips":["Set source immediately when constructing the manifest (fi.NewBytesResource or channel resource)","Prefer the builder helper that takes the manifest resource as a required argument","Lint/test: assert every registered addon manifest has both spec and source"],"tags":["addons","bootstrap-channel","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}