{"record":{"id":"bfd874bffd10fd9b","repo":"xkcoding/spring-boot-demo","slug":"client-id-s-already-exist","errorCode":null,"errorMessage":"Client id %s already exist.","messagePattern":"Client id (.+?) already exist\\.","errorType":"exception","errorClass":"ClientAlreadyExistsException","httpStatus":null,"severity":"warning","filePath":"demo-oauth/oauth-authorization-server/src/main/java/com/xkcoding/oauth/service/impl/SysClientDetailsServiceImpl.java","lineNumber":43,"sourceCode":"\n    private final SysClientDetailsRepository sysClientDetailsRepository;\n    private final PasswordEncoder passwordEncoder;\n\n    @Override\n    public ClientDetails loadClientByClientId(String id) throws ClientRegistrationException {\n        return sysClientDetailsRepository.findFirstByClientId(id).orElseThrow(() -> new ClientRegistrationException(\"Loading client exception.\"));\n    }\n\n    @Override\n    public SysClientDetails findByClientId(String clientId) {\n        return sysClientDetailsRepository.findFirstByClientId(clientId).orElseThrow(() -> new ClientRegistrationException(\"Loading client exception.\"));\n    }\n\n    @Override\n    public void addClientDetails(SysClientDetails clientDetails) throws ClientAlreadyExistsException {\n        clientDetails.setId(null);\n        if (sysClientDetailsRepository.findFirstByClientId(clientDetails.getClientId()).isPresent()) {\n            throw new ClientAlreadyExistsException(String.format(\"Client id %s already exist.\", clientDetails.getClientId()));\n        }\n        sysClientDetailsRepository.save(clientDetails);\n    }\n\n    @Override\n    public void updateClientDetails(SysClientDetails clientDetails) throws NoSuchClientException {\n        SysClientDetails exist = sysClientDetailsRepository.findFirstByClientId(clientDetails.getClientId()).orElseThrow(() -> new NoSuchClientException(\"No such client!\"));\n        clientDetails.setClientSecret(exist.getClientSecret());\n        sysClientDetailsRepository.save(clientDetails);\n    }\n\n    @Override\n    public void updateClientSecret(String clientId, String clientSecret) throws NoSuchClientException {\n        SysClientDetails exist = sysClientDetailsRepository.findFirstByClientId(clientId).orElseThrow(() -> new NoSuchClientException(\"No such client!\"));\n        exist.setClientSecret(passwordEncoder.encode(clientSecret));\n        sysClientDetailsRepository.save(exist);\n    }\n","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/xkcoding/spring-boot-demo/blob/87a142f9604c1a5365b4d24d22c2c11c26a9d5ab/demo-oauth/oauth-authorization-server/src/main/java/com/xkcoding/oauth/service/impl/SysClientDetailsServiceImpl.java#L25-L61","documentation":"Thrown by addClientDetails when a SysClientDetails with the same clientId already exists in the repository. This is Spring Security OAuth2's ClientAlreadyExistsException, part of the ClientDetailsService contract. The check queries findFirstByClientId before inserting; if present, registration is rejected.","triggerScenarios":"Calling addClientDetails(clientDetails) where clientDetails.getClientId() matches an existing row in the sys_client_details table. This occurs during OAuth2 client registration setup or when re-running a seed script.","commonSituations":"Re-running a database seed or migration script that inserts OAuth2 clients; two modules or services registering the same clientId; manual client setup via admin UI hitting a duplicate; CI/CD pipeline re-deploying with seed data that already ran.","solutions":["Check for an existing client with findByClientId(clientId) before calling addClientDetails, and call updateClientDetails instead if it exists.","Use a unique clientId for each new registration.","If re-seeding, delete the existing client first via removeClientDetails(clientId).","Handle ClientAlreadyExistsException in the calling layer and inform the user the clientId is taken."],"exampleFix":"// before — blindly calls addClientDetails\nsysClientDetailsService.addClientDetails(clientDetails);\n\n// after — check first, then add or update\nif (sysClientDetailsService.findByClientId(clientDetails.getClientId()) != null) {\n    sysClientDetailsService.updateClientDetails(clientDetails);\n} else {\n    sysClientDetailsService.addClientDetails(clientDetails);\n}","handlingStrategy":"validation","validationCode":"// Check for existing client before adding\nSysClientDetails existing = sysClientDetailsRepository\n    .findFirstByClientId(clientDetails.getClientId()).orElse(null);\nif (existing != null) {\n    // Update instead of add, or inform the caller\n    throw new IllegalArgumentException(\"ClientId already taken: \" + clientDetails.getClientId());\n}","typeGuard":null,"tryCatchPattern":"try {\n    sysClientDetailsService.addClientDetails(clientDetails);\n} catch (ClientAlreadyExistsException e) {\n    log.warn(\"Client {} already exists\", clientDetails.getClientId());\n    // Optionally update instead\n    sysClientDetailsService.updateClientDetails(clientDetails);\n}","preventionTips":["Always check findByClientId before addClientDetails to avoid the exception path.","Generate clientIds with a uniqueness guarantee (UUID or a sequence).","Handle ClientAlreadyExistsException gracefully in the calling layer."],"tags":["oauth2","spring-security","client-registration","duplicate","jpa"],"backgroundTag":null,"analyzedSha":"87a142f9604c1a5365b4d24d22c2c11c26a9d5ab","analyzedAt":"2026-08-14T01:16:58.217Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}