goharbor/harbor · error

empty rule template ID

Error message

empty rule template ID

What it means

Returned by rule index Valid(templateID, parameters) when the template ID string is empty. Rule templates (always, latestPulledN, daysSinceLastPull, etc.) are registered into an index; Valid rejects the empty key before lookup. It means a retention policy rule carries no template selector.

Source

Thrown at src/pkg/retention/policy/rule/index/index.go:185

// Register the rule evaluator with the corresponding rule template
func Register(meta *Metadata, factory rule.Factory, validator ...rule.Validator) {
	if meta == nil || factory == nil || len(meta.TemplateID) == 0 {
		// do nothing
		return
	}

	index.Store(meta.TemplateID, &indexedItem{
		Meta:       meta,
		Factory:    factory,
		Validators: validator,
	})
}

// Valid ...
func Valid(templateID string, parameters rule.Parameters) error {
	if len(templateID) == 0 {
		return errors.New("empty rule template ID")
	}

	v, ok := index.Load(templateID)
	if !ok {
		return errors.Errorf("rule evaluator %s is not registered", templateID)
	}

	item := v.(*indexedItem)

	// We can check more things if we want to do in the future
	if len(item.Meta.Parameters) > 0 {
		for _, p := range item.Meta.Parameters {
			if p.Required {
				exists := parameters != nil
				if exists {
					_, exists = parameters[p.Name]
				}

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Set a valid template ID on each rule, e.g. 'always', 'latestPushedK', 'daysSinceLastPull'
  2. Validate every rule has a non-empty template before POSTing the policy
  3. Check current template IDs supported by your Harbor version via the retention API metadata endpoint

Example fix

// before
if err := index.Valid("", params); err != nil { ... }

// after
if err := index.Valid("always", params); err != nil { ... }
Defensive patterns

Strategy: validation

Validate before calling

for _, r := range policy.Rules {
    if len(r.Template) == 0 {
        return fmt.Errorf("retention rule %v has no template", r.ID)
    }
    if err := ruleindex.Valid(r.Template, r.Params); err != nil {
        return err
    }
}

Prevention

When it happens

Trigger: Creating/updating a retention policy whose rule omits or blanks the template field; policy JSON built programmatically with an unset rule.Template; payload corruption stripping the template key.

Common situations: Scripted policy creation missing required fields; Harbor API clients with schema drift after upgrade (template renamed/required); copy-paste from old policy exports.

Related errors


AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16). Data as JSON: /api/errors/0405a1aa5fb722a3. Report an issue: GitHub.