{"record":{"id":"a12687eec88effab","repo":"spring-projects/spring-security","slug":"series-id-series-already-exists","errorCode":null,"errorMessage":"Series Id '<series>' already exists!","messagePattern":"Series Id '<series>' already exists!","errorType":"exception","errorClass":"DataIntegrityViolationException","httpStatus":null,"severity":"error","filePath":"web/src/main/java/org/springframework/security/web/authentication/rememberme/InMemoryTokenRepositoryImpl.java","lineNumber":42,"sourceCode":"import org.jspecify.annotations.Nullable;\n\nimport org.springframework.dao.DataIntegrityViolationException;\n\n/**\n * Simple <tt>PersistentTokenRepository</tt> implementation backed by a Map. Intended for\n * testing only.\n *\n * @author Luke Taylor\n */\npublic class InMemoryTokenRepositoryImpl implements PersistentTokenRepository {\n\n\tprivate final Map<String, PersistentRememberMeToken> seriesTokens = new HashMap<>();\n\n\t@Override\n\tpublic synchronized void createNewToken(PersistentRememberMeToken token) {\n\t\tPersistentRememberMeToken current = this.seriesTokens.get(token.getSeries());\n\t\tif (current != null) {\n\t\t\tthrow new DataIntegrityViolationException(\"Series Id '\" + token.getSeries() + \"' already exists!\");\n\t\t}\n\t\tthis.seriesTokens.put(token.getSeries(), token);\n\t}\n\n\t@Override\n\tpublic synchronized void updateToken(String series, String tokenValue, Date lastUsed) {\n\t\tPersistentRememberMeToken token = getTokenForSeries(series);\n\t\tif (token == null) {\n\t\t\tthrow new IllegalArgumentException(\"Token for series '\" + series + \"' does not exist\");\n\t\t}\n\t\tPersistentRememberMeToken newToken = new PersistentRememberMeToken(token.getUsername(), series, tokenValue,\n\t\t\t\tnew Date());\n\t\t// Store it, overwriting the existing one.\n\t\tthis.seriesTokens.put(series, newToken);\n\t}\n\n\t@Override\n\tpublic synchronized @Nullable PersistentRememberMeToken getTokenForSeries(String seriesId) {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/web/src/main/java/org/springframework/security/web/authentication/rememberme/InMemoryTokenRepositoryImpl.java#L24-L60","documentation":"InMemoryTokenRepositoryImpl.createNewToken refuses to overwrite an existing series and throws DataIntegrityViolationException when a PersistentRememberMeToken with the same series id is already stored. The repository mirrors the uniqueness constraint a persistent store would enforce on the series primary key.","triggerScenarios":"Calling createNewToken(token) twice with tokens having the same getSeries() value — typically because application code (not the framework) creates tokens manually, or two threads/instances share the same series generation without going through the repository's normal flow.","commonSituations":"Custom remember-me bootstrap code re-creating a token for an existing series; seeding the in-memory repository from a database that already contains the series; test code that forgets to clear the repository between cases; switching repositories (Jdbc vs InMemory) mid-flight.","solutions":["Call updateToken instead of createNewToken when the series may already exist.","Remove the existing series first with removeToken/removeUserTokens before re-creating.","Use JdbcTokenRepositoryImpl (with the DDL's primary key) for durable storage; treat this exception as a duplicate-key condition and generate a new series id.","In tests, use a fresh InMemoryTokenRepositoryImpl per test or clear state in setup."],"exampleFix":"// before\nrepository.createNewToken(new PersistentRememberMeToken(user, existingSeries, value, new Date()));\n// after\nif (repository.getTokenForSeries(existingSeries) != null) {\n    repository.removeUserTokens(user);\n}\nrepository.createNewToken(new PersistentRememberMeToken(user, UUID.randomUUID().toString(), value, new Date()));","handlingStrategy":"try-catch","validationCode":"if (repo.getTokenForSeries(token.getSeries()) != null) {\n    throw new IllegalStateException(\"series already exists: \" + token.getSeries());\n}","typeGuard":null,"tryCatchPattern":"try {\n    repo.createNewToken(token);\n} catch (DataIntegrityViolationException e) {\n    repo.updateToken(token.getSeries(), token.getTokenValue(), token.getDate());\n}","preventionTips":["Generate series ids with UUID.randomUUID() to avoid collisions","Use updateToken for existing series, createNewToken only for new ones","In tests, create a fresh InMemoryTokenRepositoryImpl per test","Prefer a persistent repository (Jdbc) that enforces the same uniqueness explicitly"],"tags":["remember-me","in-memory","duplicate-key","spring-security"],"backgroundTag":"file-already-exists","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}