{"record":{"id":"f79135f5b8d60be5","repo":"goharbor/harbor","slug":"tencent-tcr-prepareforpush-the-metadata-of-resou","errorCode":null,"errorMessage":"[tencent-tcr.PrepareForPush] the metadata of resource cannot be null","messagePattern":"\\[tencent-tcr\\.PrepareForPush\\] the metadata of resource cannot be null","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/pkg/reg/adapter/tencentcr/adapter.go","lineNumber":218,"sourceCode":"\t\t\t\tStyle: model.FilterStyleTypeText,\n\t\t\t},\n\t\t},\n\t\tSupportedTriggers: []string{\n\t\t\tmodel.TriggerTypeManual,\n\t\t\tmodel.TriggerTypeScheduled,\n\t\t},\n\t}\n\treturn\n}\n\nfunc (a *adapter) PrepareForPush(resources []*model.Resource) (err error) {\n\tlog.Debugf(\"[tencent-tcr.PrepareForPush]\")\n\tfor _, resource := range resources {\n\t\tif resource == nil {\n\t\t\treturn errors.New(\"the resource cannot be null\")\n\t\t}\n\t\tif resource.Metadata == nil {\n\t\t\treturn errors.New(\"[tencent-tcr.PrepareForPush] the metadata of resource cannot be null\")\n\t\t}\n\t\tif resource.Metadata.Repository == nil {\n\t\t\treturn errors.New(\"[tencent-tcr.PrepareForPush] the namespace of resource cannot be null\")\n\t\t}\n\t\tif len(resource.Metadata.Repository.Name) == 0 {\n\t\t\treturn errors.New(\"[tencent-tcr.PrepareForPush] the name of the namespace cannot be null\")\n\t\t}\n\t\tvar paths = strings.Split(resource.Metadata.Repository.Name, \"/\")\n\t\tvar namespace = paths[0]\n\t\tvar repository = path.Join(paths[1:]...)\n\n\t\tlog.Debugf(\"[tencent-tcr.PrepareForPush.createPrivateNamespace] namespace=%s\", namespace)\n\t\terr = a.createPrivateNamespace(namespace)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tlog.Debugf(\"[tencent-tcr.PrepareForPush.createRepository] namespace=%s, repository=%s\", namespace, repository)\n\t\terr = a.createRepository(namespace, repository)","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/src/pkg/reg/adapter/tencentcr/adapter.go#L200-L236","documentation":"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.","triggerScenarios":"Passing a resource constructed without Metadata to tencentcr PrepareForPush, e.g. a resource built only with Type or Deleted flags.","commonSituations":"Reusing deletion/listing-shaped resource objects on the push path; hand-built literals; partial clones during refactors; fixture drift between adapters' tests.","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."],"exampleFix":"// before\nres := &model.Resource{Type: model.ResourceTypeImage}\n\n// after\nres := &model.Resource{\n    Type:     model.ResourceTypeImage,\n    Metadata: &model.ResourceMetadata{\n        Repository: &model.Repository{Name: \"myns/myrepo\"},\n    },\n}","handlingStrategy":"validation","validationCode":"for i, r := range resources {\n\tif r == nil || r.Metadata == nil {\n\t\treturn fmt.Errorf(\"resources[%d]: missing resource or metadata\", i)\n\t}\n}","typeGuard":"func hasMetadata(r *model.Resource) bool { return r != nil && r.Metadata != nil }","tryCatchPattern":"if err := a.PrepareForPush(resources); err != nil {\n\tif strings.Contains(err.Error(), \"metadata of resource cannot be null\") {\n\t\t// populate Metadata (with Repository.Name) and retry\n\t}\n\treturn err\n}","preventionTips":["Single resource builder always sets Metadata.","Never reuse Metadata-less resources on push paths."],"tags":["go","tencent-tcr","replication","validation","nil-check"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}