goharbor/harbor · error

the resource cannot be null

Error message

the resource cannot be null

What it means

Returned by the JFrog Artifactory adapter's PrepareForPush (src/pkg/reg/adapter/jfrog/adapter.go:120), which pre-creates local docker repositories in Artifactory before images are pushed. The loop over resources rejects any element that is a nil *model.Resource. It throws early because later code dereferences resource.Metadata unconditionally.

Source

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

		},
	}
	return
}

func newAdapter(registry *model.Registry) (adp.Adapter, error) {
	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 {

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Find where the resource slice is built and stop appending nil entries — fail the fetch instead of inserting nil.
  2. Sanitize the slice before the call (see validationCode) so the offending index is reported.
  3. If a nil entry is legitimate 'skip' semantics in your code, filter it out before calling PrepareForPush.
  4. Upgrade/review your caller: upstream Harbor always passes fully-formed resources, so a nil element indicates a local bug.

Example fix

// before
for _, r := range fetched {
    if r == nil {
        resources = append(resources, nil) // placeholder, panics later or errors here
    } else {
        resources = append(resources, r)
    }
}

// after
for _, r := range fetched {
    if r == nil {
        return fmt.Errorf("fetch returned a nil resource")
    }
    resources = append(resources, r)
}
Defensive patterns

Strategy: validation

Validate before calling

for i, r := range resources {
	if r == nil {
		return fmt.Errorf("resources[%d] is nil; refusing to call PrepareForPush", i)
	}
}
if err := jfrogAdapter.PrepareForPush(resources); err != nil { /* ... */ }

Type guard

func isUsableResource(r *model.Resource) bool { return r != nil }

Try / catch

if err := a.PrepareForPush(resources); err != nil {
	if strings.Contains(err.Error(), "the resource cannot be null") {
		// slice construction bug: log index and rebuild resources
	}
	return err
}

Prevention

When it happens

Trigger: Calling PrepareForPush on the jfrog adapter with a nil element in the []*model.Resource slice, e.g. append(resources, nil) or a filter step that leaves nil placeholders.

Common situations: Custom transfer pipelines that append nil when an intermediate fetch fails instead of aborting; refactoring that introduces sparse slices; copy between registries where one artifact's metadata build failed silently.

Related errors


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