goharbor/harbor · error
malformed endpoint
Error message
malformed endpoint
What it means
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.
Source
Thrown at src/pkg/scan/dao/scanner/model.go:102
}
return json.Unmarshal([]byte(jsonData), r)
}
// ToJSON marshals registration to JSON data
func (r *Registration) ToJSON() (string, error) {
data, err := json.Marshal(r)
if err != nil {
return "", err
}
return string(data), nil
}
// Validate registration
func (r *Registration) Validate(checkUUID bool) error {
if checkUUID && len(r.UUID) == 0 {
return errors.New("malformed endpoint")
}
if len(r.Name) == 0 {
return errors.New("missing registration name")
}
url, err := lib.ValidateHTTPURL(r.URL)
if err != nil {
return errors.Wrap(err, "scanner registration validate")
}
r.URL = url
if len(r.Auth) > 0 &&
r.Auth != auth.Basic &&
r.Auth != auth.Bearer &&
r.Auth != auth.APIKey {
return errors.Errorf("auth type %s is not supported", r.Auth)
}View on GitHub (pinned to 7b2fd08cc5)
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
Example fix
// before reg := parseBody(r) err := reg.Validate(true) // UUID never set -> 'malformed endpoint' // after reg := parseBody(r) reg.UUID = mux.Vars(r)["uuid"] err := reg.Validate(true)
Defensive patterns
Strategy: validation
Validate before calling
// On update paths, bind the path UUID into the model first
if len(reg.UUID) == 0 {
return errors.New("scanner registration uuid is required for update")
}
err := reg.Validate(true) Type guard
func hasUUID(r *scanner.Registration) bool {
return r != nil && len(r.UUID) > 0
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- missing registration name
- missing uuid
- File {} not exist
- Internal dir for tls {} not exist
- Port number in metrics is not valid
AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16).
Data as JSON: /api/errors/481e37be7d1597f6.
Report an issue: GitHub.