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

  1. Use a service user (API token issued to a service user) as the initiator to delete integration-issued users
  2. Or disconnect/remove the integration so the user is no longer UserIssuedIntegration before deleting
  3. 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

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


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/e23d933a6d7e705c. Report an issue: GitHub.