Summary
POST /api/v2.0/projects/{id}/members returns 500 Internal Server Error with message can not get valid member entity when the request body is empty or missing all required fields. It should return 400 Bad Request with a clear validation message.
Steps to reproduce
curl -X POST -u admin:<password> \
https://<host>/api/v2.0/projects/1/members \
-H "Content-Type: application/json" \
-d "{}"
Or with a completely empty body:
curl -X POST -u admin:<password> \
https://<host>/api/v2.0/projects/1/members
Expected behavior
Return 400 Bad Request with a descriptive message, e.g.:
{
"errors": [{
"code": "BAD_REQUEST",
"message": "at least one of member_user or member_group must be provided"
}]
}
Actual behavior
Returns 500 Internal Server Error:
can not get valid member entity, request: {ProjectID:0 Role:0 MemberUser:{UserID:0 Username:} MemberGroup:{ID:0 GroupName: GroupType:0 LdapGroupDN:}}
Root cause
In src/controller/member/controller.go, the Create() function (line 122) does not validate the request at entry. When all fields in Request are zero-valued, none of the if/else if branches match, member.EntityID stays 0, and the function falls through to:
// line 205
if member.EntityID <= 0 {
return 0, fmt.Errorf("can not get valid member entity, request: %+v", req)
}
This returns a generic error (not a typed BadRequestError), which surfaces as 500.
Suggested fix
Add early validation at the top of Create():
func (c *controller) Create(ctx context.Context, projectNameOrID any, req Request) (int, error) {
// ... existing project lookup ...
if req.MemberUser.UserID == 0 &&
req.MemberUser.Username == "" &&
req.MemberGroup.ID == 0 &&
req.MemberGroup.GroupName == "" &&
req.MemberGroup.LdapGroupDN == "" {
return 0, errors.BadRequestError(nil).
WithMessage("at least one of member_user or member_group must be provided")
}
// ... rest of existing logic ...
}
Environment
- Harbor version: v2.15.2
- Deployment: HA (2 nodes), external PostgreSQL 15, external Redis 7
Context
Discovered while investigating issue #23608 — the can not get valid member entity error appeared alongside an unrelated retention job failure. Confirmed to be caused by an external script sending empty-body POST requests to the member API.
Reporter: zhangxiaopeng@zgci.ac.cn
Summary
POST /api/v2.0/projects/{id}/membersreturns 500 Internal Server Error with messagecan not get valid member entitywhen the request body is empty or missing all required fields. It should return 400 Bad Request with a clear validation message.Steps to reproduce
Or with a completely empty body:
Expected behavior
Return
400 Bad Requestwith a descriptive message, e.g.:{ "errors": [{ "code": "BAD_REQUEST", "message": "at least one of member_user or member_group must be provided" }] }Actual behavior
Returns
500 Internal Server Error:Root cause
In
src/controller/member/controller.go, theCreate()function (line 122) does not validate the request at entry. When all fields inRequestare zero-valued, none of theif/else ifbranches match,member.EntityIDstays0, and the function falls through to:This returns a generic
error(not a typedBadRequestError), which surfaces as 500.Suggested fix
Add early validation at the top of
Create():Environment
Context
Discovered while investigating issue #23608 — the
can not get valid member entityerror appeared alongside an unrelated retention job failure. Confirmed to be caused by an external script sending empty-body POST requests to the member API.Reporter: zhangxiaopeng@zgci.ac.cn