goharbor/harbor · error

the name of namespace cannot be null

Error message

the name of namespace cannot be null

What it means

Returned by the JFrog Artifactory adapter's PrepareForPush (src/pkg/reg/adapter/jfrog/adapter.go:129) when resource.Metadata.Repository exists but its Name is "". The adapter splits the name on "/" and uses path[0] as the Artifactory local repository to create, so an empty name cannot map to any repository.

Source

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

		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{}{}
	}

	for _, namespace := range namespaces {
		if _, ok := existedRepositories[namespace]; ok {

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Ensure the repository name is propagated (e.g. from the source resource) before calling PrepareForPush: resource.Metadata.Repository.Name = srcRepoName.
  2. Pre-validate names with the helper below so you know which index failed.
  3. If the name is computed from a rule, unit-test the computation against edge cases (empty filters, missing namespace).
  4. Log the full resource before the call when debugging replication failures.

Example fix

// before
Repository: &model.Repository{},

// after
Repository: &model.Repository{Name: "docker-local/" + src.Metadata.Repository.Name},
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

if err := a.PrepareForPush(resources); err != nil {
	if strings.Contains(err.Error(), "name of namespace cannot be null") {
		// empty Repository.Name: propagate source repo name and retry
	}
	return err
}

Prevention

When it happens

Trigger: Calling jfrog PrepareForPush with a resource whose Repository struct is present but Name was never assigned — typically after an override strips the name or a clone misses the field.

Common situations: Destination-name templating that evaluates to empty; struct copies that keep the Repository pointer but overwrite Name; test fixtures with &model.Repository{} placeholders.

Related errors


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