kubernetes/kops · error

error rendering addon %q template: %w

Error message

error rendering addon %q template: %w

What it means

After reading the raw manifest bytes, AddonManifest.Normalize optionally renders the addon template through a.addonRenderer.RenderTemplate, passing the addon location and all tasks visible to addons. If template rendering fails (missing/unknown template variable, bad template syntax, task lookup issues), the error is wrapped with %w so the underlying template error is preserved and the addon name is included.

Source

Thrown at upup/pkg/fi/cloudup/bootstrapchannelbuilder/addonmanifest.go:92

}

func (a *AddonManifest) Normalize(c *fi.CloudupContext) error {
	if a.addonSpec == nil {
		return fmt.Errorf("addon spec is not configured for %q", fi.ValueOf(a.Name))
	}
	if a.source == nil {
		return fmt.Errorf("addon source is not configured for %q", fi.ValueOf(a.Name))
	}

	manifestBytes, err := fi.ResourceAsBytes(a.source)
	if err != nil {
		return fmt.Errorf("error reading addon %q manifest: %v", fi.ValueOf(a.Name), err)
	}

	if !a.skipRender && a.addonRenderer != nil {
		manifestBytes, err = a.addonRenderer.RenderTemplate(fi.ValueOf(a.Location), manifestBytes, tasksVisibleToAddons(c.AllTasks()))
		if err != nil {
			return fmt.Errorf("error rendering addon %q template: %w", fi.ValueOf(a.Name), err)
		}
	}

	if !a.skipRemap {
		manifestBytes, err = addonmanifests.RemapAddonManifest(a.addonSpec, a.modelContext, a.assetBuilder, manifestBytes, a.serviceAccounts)
		if err != nil {
			klog.Infof("invalid manifest: %s", string(manifestBytes))
			return fmt.Errorf("error remapping manifest %s: %v", fi.ValueOf(a.Location), err)
		}
	}

	manifestBytes = []byte(strings.TrimSpace(string(manifestBytes)))

	if a.buildPrune {
		if err := buildPruneDirectives(a.addonSpec, manifestBytes); err != nil {
			return fmt.Errorf("failed to configure pruning for %s: %w", fi.ValueOf(a.addonSpec.Name), err)
		}
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Read the wrapped cause (the %w chain) to identify the exact template/variable failure
  2. Check every {{ ... }} placeholder in the addon manifest is supported by the renderer and resolvable from the tasks visible to addons
  3. If this addon needs no templating, mark it as a raw source (skipRender path) instead of a template
  4. If a kOps upgrade broke the template, update the addon manifest template to the new context/fields or pin the addon version
  5. Run the failing addon's template render in isolation (go test in bootstrapchannelbuilder) to iterate quickly

Example fix

// before (template references unknown field)
image: {{ .NonExistentTask.Image }}
// after
image: {{ .Image }}  // or a field exposed via tasksVisibleToAddons
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check template placeholders against renderer-supported keys
for _, key := range extractTemplateKeys(manifestBytes) {
    if !rendererSupports(key) {
        return fmt.Errorf("unsupported template key %s in addon %s", key, addonName)
    }
}

Try / catch

if err := m.Normalize(ctx); err != nil {
    var tmplErr error
    if errors.As(err, &tmplErr) && strings.Contains(err.Error(), "error rendering addon") {
        log.Printf("template failure for %s: %v", name, err) // %w chain has root cause
    }
}

Prevention

When it happens

Trigger: Normalize runs (covered by the two TestAddonManifestNormalize* tests) with skipRender=false and addonRenderer non-nil, and RenderTemplate returns an error — typically an unresolvable template placeholder for the cluster/tasks context or a malformed template in the addon manifest.

Common situations: A custom addon template references a variable that is not among tasksVisibleToAddons(c.AllTasks()) or not exposed by the renderer; Go template syntax errors in a hand-written addon manifest; kOps upgrade changes the template context so an old template's field no longer exists.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/01213acd3b1dc8af. Report an issue: GitHub.