netbirdio/netbird · error
only integration service user can delete this user
Error message
only integration service user can delete this user
What it means
Returned in AccountManager.DeleteUsers (management/server/user.go:1288): users created by an integration (targetUser.Issued == types.UserIssuedIntegration) may only be deleted by a service-user initiator (initiatorUser.IsServiceUser). Regular human admins and owners get this error so integration-owned lifecycle stays under integration control.
Source
Thrown at management/server/user.go:1288
if initiatorUserID == targetUserID {
allErrors = errors.Join(allErrors, errors.New("self deletion is not allowed"))
continue
}
targetUser, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthNone, targetUserID)
if err != nil {
allErrors = errors.Join(allErrors, err)
continue
}
if targetUser.Role == types.UserRoleOwner {
allErrors = errors.Join(allErrors, fmt.Errorf("unable to delete a user: %s with owner role", targetUserID))
continue
}
// disable deleting integration user if the initiator is not admin service user
if targetUser.Issued == types.UserIssuedIntegration && !initiatorUser.IsServiceUser {
allErrors = errors.Join(allErrors, errors.New("only integration service user can delete this user"))
continue
}
userInfo, ok := userInfos[targetUserID]
if !ok || userInfo == nil {
allErrors = errors.Join(allErrors, fmt.Errorf("user info not found for user: %s", targetUserID))
continue
}
_, err = am.deleteRegularUser(ctx, accountID, initiatorUserID, userInfo)
if err != nil {
allErrors = errors.Join(allErrors, err)
continue
}
}
return allErrors
}View on GitHub (pinned to 93e97f4bf1)
Solutions
- Use a service user (API token issued to a service user) as the initiator to delete integration-issued users
- Or disconnect/remove the integration so the user is no longer UserIssuedIntegration before deleting
- Exclude integration-issued users from bulk delete lists when running as a human admin
Example fix
// before: human admin tries to delete an integration-issued user
am.DeleteUsers(ctx, accountID, humanAdminID, []string{integrationUserID})
// after: perform the call with a service-user initiator
am.DeleteUsers(ctx, accountID, serviceUserID, []string{integrationUserID}) Defensive patterns
Strategy: validation
Validate before calling
// Skip integration-issued users unless running as a service user
func deletableByHuman(u *types.User) bool {
return u.Issued != types.UserIssuedIntegration
}
if initiatorUser.IsServiceUser || deletableByHuman(targetUser) {
// safe to include in the delete batch
} Try / catch
err := am.DeleteUsers(ctx, accountID, initiatorID, targets)
if err != nil && strings.Contains(err.Error(), "only integration service user can delete this user") {
// re-run the batch with a service-user initiator or exclude these targets
} Prevention
- Provision deletions of integration users through the integration's own service-user token
- Check the Issued field when enumerating deletable users in admin tooling
- Keep one dedicated service user with the Users module permission for lifecycle automation
When it happens
Trigger: A human admin (non-service user) calls delete-users with the ID of a user that was provisioned by an integration; the check fires per-target and is joined into the aggregate error.
Common situations: SCIM/IdP-provisioned users appearing in the account; admin trying to clean up leftover service accounts from an old integration; bulk delete over the full user list that includes integration-managed entries.
Related errors
- self deletion is not allowed
- router not part of network
- peer and peer_groups cannot be set at the same time
- either peer or peer_groups must be provided
- posture checks name shouldn't be empty
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/e23d933a6d7e705c.
Report an issue: GitHub.