pinpoint-apm/pinpoint · warning · PinpointUserGroupException

userGroup's name already exist. :

Error message

userGroup's name already exist. :

What it means

createUserGroup checks userGroupDao.isExistUserGroup(userGroup.getId()) first and throws PinpointUserGroupException when a group with that ID (name) already exists, preventing duplicate user group names in the store.

Solutions

  1. Check existence (isExistUserGroup) before creating and reuse the existing group.
  2. Catch PinpointUserGroupException and treat it as an idempotent success if the existing group is acceptable.
  3. Use a unique group id/name.

Example fix

// before
userGroupService.createUserGroup(new UserGroup("devs")); // second call
// after
if (!userGroupService.isExistUserGroup("devs")) {
    userGroupService.createUserGroup(new UserGroup("devs"));
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (userGroupDao.isExistUserGroup(groupId)) { /* reuse existing group or reject in UI */ }

Try / catch

try { userGroupService.createUserGroup(group); } catch (PinpointUserGroupException e) { /* treat as already-exists, load existing group */ }

Prevention

When it happens

Trigger: Calling createUserGroup with a UserGroup whose id equals an existing group's id; double form submissions creating the same group twice.

Common situations: UI retry after a slow response re-POSTs the create request; scripted provisioning run twice; case-sensitivity surprises between stored and requested names.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07). Data as JSON: /api/errors/e9e64c621a487169. Report an issue: GitHub.

Appendix: source

Thrown at user/src/main/java/com/navercorp/pinpoint/user/service/UserGroupServiceImpl.java:89

    @Autowired
    public UserGroupServiceImpl(@Qualifier("mysqlUserGroupDao") UserGroupDao userGroupDao,
                                Optional<UserInfoDecoder> userInfoDecoder,
                                UserConfigProperties userConfigProperties,
                                UserService userService,
                                List<UserGroupDeletionListener> userGroupDeletionListeners) {
        this.userGroupDao = Objects.requireNonNull(userGroupDao, "userGroupDao");
        this.userInfoDecoder = Objects.requireNonNull(userInfoDecoder, "userInfoDecoder").orElse(DefaultUserInfoDecoder.EMPTY_USER_INFO_DECODER);
        this.userConfigProperties = Objects.requireNonNull(userConfigProperties, "userConfigProperties");
        this.userService = Objects.requireNonNull(userService, "userService");
        this.userGroupDeletionListeners = List.copyOf(
                Objects.requireNonNull(userGroupDeletionListeners, "userGroupDeletionListeners")
        );
    }

    @Override
    public String createUserGroup(UserGroup userGroup) throws PinpointUserGroupException {
        if (userGroupDao.isExistUserGroup(userGroup.getId())) {
            throw new PinpointUserGroupException("userGroup's name already exist. :" + userGroup.getId());
        }

        String userGroupNumber = userGroupDao.createUserGroup(userGroup);

        if (!userConfigProperties.isOpenSource()) {
            String userId = userService.getUserIdFromSecurity();
            if (StringUtils.isEmpty(userId)) {
                throw new PinpointUserGroupException("There is not userId or fail to create userGroup.");
            }

            insertMember(new UserGroupMember(userGroup.getId(), userId));
        }

        return userGroupNumber;
    }

    @Override
    @Transactional(readOnly = true)

View on GitHub (pinned to 744c3d3075)