goharbor/harbor · error

[volcengine-cr.PrepareForPush] the metadata of resource cann

Error message

[volcengine-cr.PrepareForPush] the metadata of resource cannot be null

What it means

Returned by the Volcengine CR adapter's PrepareForPush (src/pkg/reg/adapter/volcenginecr/adapter.go:138) when a resource is non-nil but resource.Metadata is nil. The adapter needs Metadata.Repository.Name to derive the namespace/repository pair it creates in Volcengine CR (it additionally requires len(paths) >= 2, i.e. both namespace and repository segments).

Source

Thrown at src/pkg/reg/adapter/volcenginecr/adapter.go:138

				Type:  model.FilterTypeTag,
				Style: model.FilterStyleTypeText,
			},
		},
		SupportedTriggers: []string{
			model.TriggerTypeManual,
			model.TriggerTypeScheduled,
		},
	}
	return
}

func (a *adapter) PrepareForPush(resources []*model.Resource) (err error) {
	for _, resource := range resources {
		if resource == nil {
			return errors.New("the resource cannot be null")
		}
		if resource.Metadata == nil {
			return errors.New("[volcengine-cr.PrepareForPush] the metadata of resource cannot be null")
		}
		if resource.Metadata.Repository == nil {
			return errors.New("[volcengine-cr.PrepareForPush] the namespace of resource cannot be null")
		}
		if len(resource.Metadata.Repository.Name) == 0 {
			return errors.New("[volcengine-cr.PrepareForPush] the name of the namespace cannot be null")
		}
		var paths = strings.Split(resource.Metadata.Repository.Name, "/")
		if len(paths) < 2 {
			return errors.New("[volcengine-cr.PrepareForPush] the name of the repository and namespace cannot be null")
		}
		var namespace = paths[0]
		var repository = path.Join(paths[1:]...)

		log.Debugf("namespace=%s", namespace)
		err = a.createNamespace(namespace)
		if err != nil {
			log.Errorf("PrepareForPush error :%v", err)

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Set resource.Metadata (with Repository.Name) for all pushed resources.
  2. Validate up front with the helper below for an indexed message.
  3. Note volcenginecr additionally requires a '/' in the name — use 'namespace/repository' form.
  4. Centralize construction in a tested builder.

Example fix

// before
res := &model.Resource{Type: model.ResourceTypeImage}

// after
res := &model.Resource{
    Type:     model.ResourceTypeImage,
    Metadata: &model.ResourceMetadata{
        Repository: &model.Repository{Name: "myteam/myrepo"},
    },
}
Defensive patterns

Strategy: validation

Validate before calling

for i, r := range resources {
	if r == nil || r.Metadata == nil {
		return fmt.Errorf("resources[%d]: missing resource or metadata", i)
	}
	if r.Metadata.Repository == nil || !strings.Contains(r.Metadata.Repository.Name, "/") {
		return fmt.Errorf("resources[%d]: need 'namespace/repository' name", i)
	}
}

Type guard

func hasMetadata(r *model.Resource) bool { return r != nil && r.Metadata != nil }

Try / catch

if err := a.PrepareForPush(resources); err != nil {
	if strings.Contains(err.Error(), "metadata of resource cannot be null") {
		// populate Metadata and retry
	}
	return err
}

Prevention

When it happens

Trigger: Calling volcenginecr PrepareForPush with a resource built without the Metadata field set.

Common situations: Reusing resource objects shaped for deletion/listing (no Metadata) on the push path; hand-written literals; partial clones after refactors.

Related errors


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