goharbor/harbor · error

the namespace of resource cannot be null

Error message

the namespace of resource cannot be null

What it means

Returned by the JFrog Artifactory adapter's PrepareForPush (src/pkg/reg/adapter/jfrog/adapter.go:126) when resource.Metadata is non-nil but resource.Metadata.Repository is nil. The adapter needs the Repository pointer to read Name and split out the Artifactory repository key, so a missing Repository aborts push preparation for the entire batch.

Source

Thrown at src/pkg/reg/adapter/jfrog/adapter.go:126

	return &adapter{
		Adapter:  native.NewAdapter(registry),
		registry: registry,
		client:   newClient(registry),
	}, nil
}

// PrepareForPush creates local docker repository in jfrog artifactory
func (a *adapter) PrepareForPush(resources []*model.Resource) error {
	var namespaces []string
	for _, resource := range resources {
		if resource == nil {
			return errors.New("the resource cannot be null")
		}
		if resource.Metadata == nil {
			return errors.New("the metadata of resource cannot be null")
		}
		if resource.Metadata.Repository == nil {
			return errors.New("the namespace of resource cannot be null")
		}
		if len(resource.Metadata.Repository.Name) == 0 {
			return errors.New("the name of namespace cannot be null")
		}
		path := strings.Split(resource.Metadata.Repository.Name, "/")
		if len(path) > 0 {
			namespaces = append(namespaces, path[0])
		}
	}

	repositories, err := a.listAllRepositories()
	if err != nil {
		return err
	}
	existedRepositories := make(map[string]struct{})
	for _, repo := range repositories {
		existedRepositories[repo.Key] = struct{}{}
	}

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Set Metadata.Repository = &model.Repository{Name: ...} whenever the resource will be pushed.
  2. Pre-validate the slice (see validationCode) to get the failing index instead of the adapter's opaque message.
  3. Fix the construction site: ensure metadata cloning copies Repository by reference or value consistently.
  4. Write a unit test over your resource builder asserting Repository is non-nil for push resources.

Example fix

// before
Metadata: &model.ResourceMetadata{
    Vtags: []string{"v1"},
},

// after
Metadata: &model.ResourceMetadata{
    Repository: &model.Repository{Name: "docker-local/ubuntu"},
    Vtags:     []string{"v1"},
},
Defensive patterns

Strategy: validation

Validate before calling

for i, r := range resources {
	if r == nil || r.Metadata == nil || r.Metadata.Repository == nil {
		return fmt.Errorf("resources[%d]: nil resource/metadata/repository", i)
	}
}

Type guard

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

Try / catch

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

Prevention

When it happens

Trigger: Building a model.ResourceMetadata with only Vtags or Artifact fields set (Repository omitted), then calling PrepareForPush on the jfrog adapter.

Common situations: Resources assembled for tag-listing or deletion where Repository is not needed and therefore omitted, later fed into the push path; struct-literal refactors that drop fields; copy loops that clone only some fields of the source metadata.

Related errors


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