sqshq/piggymetrics · error · IllegalArgumentException
user already exists: + it.getUsername()
Error message
user already exists: + it.getUsername()
What it means
UserServiceImpl.create() checks UserRepository for an existing user with the same username before saving. If repository.findById(user.getUsername()) returns a present Optional, it throws IllegalArgumentException with the conflicting username. This is an application-level uniqueness guard for the user entity's primary key, thrown before any password hashing or persistence occurs.
Solutions
- Check existence before creating: if (repository.findById(user.getUsername()).isPresent()) { handle already-registered path (return, or surface a friendly 'username taken' response) }
- Catch IllegalArgumentException around the create() call and map it to an HTTP 409 Conflict response instead of a 500.
- If the user should be upserted, replace the guard with repository.save(user) directly (or findById(...).map(update).orElseGet(create)).
- Ensure callers use idempotency keys or check the account-service side so retried registrations don't re-enter create().
Example fix
// before
Optional<User> existing = repository.findById(user.getUsername());
existing.ifPresent(it -> { throw new IllegalArgumentException("user already exists: " + it.getUsername()); });
// after
if (repository.findById(user.getUsername()).isPresent()) {
throw new UserExistsException(user.getUsername()); // map to 409 Conflict in the controller/@ControllerAdvice
}
// or, for idempotent upsert semantics:
// repository.save(user); Defensive patterns
Strategy: try-catch
Validate before calling
// caller-side pre-check before invoking create()
if (userRepository.findById(user.getUsername()).isPresent()) {
// username already taken — return 409 Conflict or merge instead of creating
return;
} Type guard
// Java: Optional-based narrowing
Optional<User> existing = repository.findById(user.getUsername());
if (existing.isPresent()) {
User conflict = existing.get(); // safely narrowed, no exception path
return;
} Try / catch
try {
userService.create(user);
} catch (IllegalArgumentException e) {
// duplicate username
return ResponseEntity.status(HttpStatus.CONFLICT).body("username already exists");
} Prevention
- Always check repository.findById(username) before calling create() for new registrations.
- Return HTTP 409 Conflict (not 500) when the username is taken, via a @ControllerAdvice mapping IllegalArgumentException.
- Make client registration flows idempotent: treat 'already exists' as success-or-conflict rather than retrying blindly.
- Consider a custom exception (e.g., UserExistsException) instead of IllegalArgumentException so duplicate-vs-bug can be distinguished by callers.
- Back the username with a database unique constraint so race conditions between check and save are also caught.
When it happens
Trigger: Calling create(User) with a user whose getUsername() matches a user already persisted in the repository (e.g., POST /users with a username that was previously registered, or retrying a registration request that already succeeded).
Common situations: Duplicate registration attempts from a double-clicked signup form or retried HTTP request without idempotency handling; a microservice (e.g., account-service) provisioning a user that already exists in auth-service's database; test fixtures or seed data re-run against a persistent database; missing a pre-check like repository.findById(username).isPresent() on the client side before invoking create().
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.
AI-assisted analysis of sqshq/piggymetrics@6bb2cf9ddb (2026-09-07).
Data as JSON: /api/errors/2c5fd0f36864fb85.
Report an issue: GitHub.
Appendix: source
Thrown at auth-service/src/main/java/com/piggymetrics/auth/service/UserServiceImpl.java:28
import org.springframework.util.Assert;
import java.util.Optional;
@Service
public class UserServiceImpl implements UserService {
private final Logger log = LoggerFactory.getLogger(getClass());
private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
@Autowired
private UserRepository repository;
@Override
public void create(User user) {
Optional<User> existing = repository.findById(user.getUsername());
existing.ifPresent(it-> {throw new IllegalArgumentException("user already exists: " + it.getUsername());});
String hash = encoder.encode(user.getPassword());
user.setPassword(hash);
repository.save(user);
log.info("new user has been created: {}", user.getUsername());
}
}
View on GitHub (pinned to 6bb2cf9ddb)