goharbor/harbor · error
[tencent-tcr.PrepareForPush] the metadata of resource cannot
Error message
[tencent-tcr.PrepareForPush] the metadata of resource cannot be null
What it means
Returned by the Tencent TCR adapter's PrepareForPush (src/pkg/reg/adapter/tencentcr/adapter.go:218) when a resource is non-nil but resource.Metadata is nil. The adapter must read Metadata.Repository.Name to derive both the TCR namespace (paths[0]) and repository (path.Join(paths[1:]...)) it will create via the Tencent API.
Source
Thrown at src/pkg/reg/adapter/tencentcr/adapter.go:218
Style: model.FilterStyleTypeText,
},
},
SupportedTriggers: []string{
model.TriggerTypeManual,
model.TriggerTypeScheduled,
},
}
return
}
func (a *adapter) PrepareForPush(resources []*model.Resource) (err error) {
log.Debugf("[tencent-tcr.PrepareForPush]")
for _, resource := range resources {
if resource == nil {
return errors.New("the resource cannot be null")
}
if resource.Metadata == nil {
return errors.New("[tencent-tcr.PrepareForPush] the metadata of resource cannot be null")
}
if resource.Metadata.Repository == nil {
return errors.New("[tencent-tcr.PrepareForPush] the namespace of resource cannot be null")
}
if len(resource.Metadata.Repository.Name) == 0 {
return errors.New("[tencent-tcr.PrepareForPush] the name of the namespace cannot be null")
}
var paths = strings.Split(resource.Metadata.Repository.Name, "/")
var namespace = paths[0]
var repository = path.Join(paths[1:]...)
log.Debugf("[tencent-tcr.PrepareForPush.createPrivateNamespace] namespace=%s", namespace)
err = a.createPrivateNamespace(namespace)
if err != nil {
return
}
log.Debugf("[tencent-tcr.PrepareForPush.createRepository] namespace=%s, repository=%s", namespace, repository)
err = a.createRepository(namespace, repository)View on GitHub (pinned to 7b2fd08cc5)
Solutions
- Populate resource.Metadata together with Metadata.Repository before calling PrepareForPush.
- Use the pre-flight validation helper for an indexed, adapter-agnostic error message.
- Grep 'model.Resource{' literals on push paths and require Metadata.
- Centralize resource construction in one 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: "myns/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)
}
} 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 (with Repository.Name) and retry
}
return err
} Prevention
- Single resource builder always sets Metadata.
- Never reuse Metadata-less resources on push paths.
When it happens
Trigger: Passing a resource constructed without Metadata to tencentcr PrepareForPush, e.g. a resource built only with Type or Deleted flags.
Common situations: Reusing deletion/listing-shaped resource objects on the push path; hand-built literals; partial clones during refactors; fixture drift between adapters' tests.
Related errors
- the resource cannot be null
- [tencent-tcr.PrepareForPush] the namespace of resource canno
- the name of the repository cannot be null
- the resource cannot be null
- the metadata of resource cannot be null
AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16).
Data as JSON: /api/errors/f79135f5b8d60be5.
Report an issue: GitHub.