{"record":{"id":"89a66309dfa589d1","repo":"goharbor/harbor","slug":"bad-request-89a663","errorCode":"BAD_REQUEST","errorMessage":"name cannot be empty","messagePattern":"name cannot be empty","errorType":"validation","errorClass":"lib/errors.Error","httpStatus":400,"severity":"warning","filePath":"src/controller/registry/controller.go","lineNumber":90,"sourceCode":"\t}\n}\n\ntype controller struct {\n\tregMgr reg.Manager\n\trepMgr replication.Manager\n\tproMgr project.Manager\n}\n\nfunc (c *controller) Create(ctx context.Context, registry *model.Registry) (int64, error) {\n\tif err := c.validate(ctx, registry); err != nil {\n\t\treturn 0, err\n\t}\n\treturn c.regMgr.Create(ctx, registry)\n}\n\nfunc (c *controller) validate(ctx context.Context, registry *model.Registry) error {\n\tif len(registry.Name) == 0 {\n\t\treturn errors.New(nil).WithCode(errors.BadRequestCode).WithMessage(\"name cannot be empty\")\n\t}\n\tif len(registry.Name) > 64 {\n\t\treturn errors.New(nil).WithCode(errors.BadRequestCode).WithMessage(\"the max length of name is 64\")\n\t}\n\turl, err := lib.ValidateHTTPURL(registry.URL)\n\tif err != nil {\n\t\treturn err\n\t}\n\tregistry.URL = url\n\n\thealthy, err := c.IsHealthy(ctx, registry)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !healthy {\n\t\treturn errors.New(nil).WithCode(errors.BadRequestCode).WithMessage(\"the registry is unhealthy\")\n\t}\n\tregistry.Status = model.Healthy","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/src/controller/registry/controller.go#L72-L108","documentation":"Registry validate() is called on create (and update) and first checks the registry name: an empty name yields BAD_REQUEST 'name cannot be empty'. The name is a required identifier for the registry entry, so the request is rejected before URL or health checks run.","triggerScenarios":"POST /api/v2/registries with a JSON body missing the name field or with name:\"\"; automation templates omitting the name key.","commonSituations":"Copy-pasted payload edited to remove the name; Terraform/Ansible module variable left empty; client struct zero value marshalled.","solutions":["Include a non-empty, descriptive name (1-64 chars) in the registry payload.","Validate the payload client-side before the API call.","Check for whitespace-only names - they pass this check but fail elsewhere; trim first."],"exampleFix":"# before\nPOST /api/v2/registries\n{\"url\": \"https://docker.io\", \"type\": \"docker-hub\"}\n\n# after\nPOST /api/v2/registries\n{\"name\": \"docker-hub\", \"url\": \"https://docker.io\", \"type\": \"docker-hub\"}","handlingStrategy":"validation","validationCode":"func validRegistryName(name string) error {\n    name = strings.TrimSpace(name)\n    if name == \"\" { return fmt.Errorf(\"name cannot be empty\") }\n    if len(name) > 64 { return fmt.Errorf(\"the max length of name is 64\") }\n    return nil\n}\n// run before POST/PUT /api/v2/registries","typeGuard":"func hasRegistryName(r *model.Registry) bool {\n    return r != nil && strings.TrimSpace(r.Name) != \"\n}","tryCatchPattern":"if _, err := regCtl.Create(ctx, r); err != nil {\n    if liberrors.IsErr(err, liberrors.BadRequestCode) && err.Error() == \"name cannot be empty\" {\n        // payload bug: add name field, do not retry unchanged\n    }\n    return err\n}","preventionTips":["Trim and require name in payload templates and IaC modules.","Add client-side schema checks (JSON schema minLength: 1).","Reject zero-value structs before marshalling."],"tags":["registry","validation","bad-request","create"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}