{"record":{"id":"481e37be7d1597f6","repo":"goharbor/harbor","slug":"malformed-endpoint","errorCode":null,"errorMessage":"malformed endpoint","messagePattern":"malformed endpoint","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"src/pkg/scan/dao/scanner/model.go","lineNumber":102,"sourceCode":"\t}\n\n\treturn json.Unmarshal([]byte(jsonData), r)\n}\n\n// ToJSON marshals registration to JSON data\nfunc (r *Registration) ToJSON() (string, error) {\n\tdata, err := json.Marshal(r)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn string(data), nil\n}\n\n// Validate registration\nfunc (r *Registration) Validate(checkUUID bool) error {\n\tif checkUUID && len(r.UUID) == 0 {\n\t\treturn errors.New(\"malformed endpoint\")\n\t}\n\n\tif len(r.Name) == 0 {\n\t\treturn errors.New(\"missing registration name\")\n\t}\n\n\turl, err := lib.ValidateHTTPURL(r.URL)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"scanner registration validate\")\n\t}\n\tr.URL = url\n\n\tif len(r.Auth) > 0 &&\n\t\tr.Auth != auth.Basic &&\n\t\tr.Auth != auth.Bearer &&\n\t\tr.Auth != auth.APIKey {\n\t\treturn errors.Errorf(\"auth type %s is not supported\", r.Auth)\n\t}","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/src/pkg/scan/dao/scanner/model.go#L84-L120","documentation":"Returned by scanner Registration.Validate when checkUUID is true and the registration's UUID is empty. Despite the 'malformed endpoint' wording, the guard actually checks the UUID: it exists so update paths (which must reference an existing registration) fail fast when the UUID was not set.","triggerScenarios":"Calling Validate(true) on a Registration built without a UUID, typically before an update/delete by UUID; API PUT to /scanners/{uuid} where the payload deserialization left UUID empty; internal code reusing the Create-validation path for updates.","commonSituations":"Scanner registration update requests where the path UUID is not copied into the model; API clients sending the registration body without the uuid field on update; the misleading message sending developers to debug the URL instead of the UUID.","solutions":["Set r.UUID from the request path/payload before validating on update flows","For creation flows, call Validate(false) so the UUID guard is skipped","Ignore the message wording: it is the UUID that is missing, not the endpoint URL"],"exampleFix":"// before\nreg := parseBody(r)\nerr := reg.Validate(true) // UUID never set -> 'malformed endpoint'\n\n// after\nreg := parseBody(r)\nreg.UUID = mux.Vars(r)[\"uuid\"]\nerr := reg.Validate(true)","handlingStrategy":"validation","validationCode":"// On update paths, bind the path UUID into the model first\nif len(reg.UUID) == 0 {\n    return errors.New(\"scanner registration uuid is required for update\")\n}\nerr := reg.Validate(true)","typeGuard":"func hasUUID(r *scanner.Registration) bool {\n    return r != nil && len(r.UUID) > 0\n}","tryCatchPattern":null,"preventionTips":["Remember the message lies: 'malformed endpoint' here means missing UUID","Pass Validate(false) only on create, Validate(true) on update","Integration-test update flows to catch deserialization dropping the uuid"],"tags":["scanner","registration","uuid","validation"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}