goharbor/harbor · error
the metadata of resource cannot be null
Error message
the metadata of resource cannot be null
What it means
Returned by the JFrog Artifactory adapter's PrepareForPush (src/pkg/reg/adapter/jfrog/adapter.go:123) when a resource in the slice is non-nil but its Metadata field is nil. The adapter needs resource.Metadata.Repository to derive the Artifactory repository (namespace) to pre-create, so a missing Metadata struct aborts the whole push preparation.
Source
Thrown at src/pkg/reg/adapter/jfrog/adapter.go:123
}
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 {
return err
}
existedRepositories := make(map[string]struct{})View on GitHub (pinned to 7b2fd08cc5)
Solutions
- Always populate resource.Metadata (&model.ResourceMetadata{}) when building push resources; only the nil-resource case is tolerated less strictly than this.
- Add a pre-flight validation pass that rejects nil Metadata with the element index (see validationCode).
- Check the construction site: grep for 'model.Resource{' in your code and confirm every push-path literal includes Metadata.
- In tests, use the same builders production code uses instead of hand-rolled literals.
Example fix
// before
res := &model.Resource{
Type: model.ResourceTypeImage,
}
// after
res := &model.Resource{
Type: model.ResourceTypeImage,
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{Name: "docker-local/ubuntu"},
},
} Defensive patterns
Strategy: validation
Validate before calling
for i, r := range resources {
if r == nil || r.Metadata == nil {
return fmt.Errorf("resources[%d]: nil resource or metadata", 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") {
// fix construction site: resource literals must include Metadata
}
return err
} Prevention
- Require Metadata in the resource builder used by both prod and tests.
- Do not reuse deletion-shaped (Metadata-less) resources on push paths.
- Assert invariants in builder unit tests.
When it happens
Trigger: Passing a *model.Resource constructed as &model.Resource{...} without the Metadata field set — e.g. only Type or Deleted flags populated — to PrepareForPush on the jfrog adapter.
Common situations: Building partial Resource objects in tests or custom copiers; code that constructs a resource for deletion (where Metadata may be omitted) and reuses the same path for push; refactors that move Metadata population into an optional branch.
Related errors
- the resource cannot be null
- the namespace of resource cannot be null
- the name of namespace cannot be null
- the name of the repository cannot be null
- the resource cannot be null
AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16).
Data as JSON: /api/errors/49abcc556c713f22.
Report an issue: GitHub.