spring-projects/spring-security · error · IllegalStateException
Duplicate key ${registrationId}
Error message
Duplicate key ${registrationId} What it means
InMemoryReactiveClientRegistrationRepository stores ClientRegistrations in an unmodifiable map keyed by registrationId. During construction it detects two registrations with the same registrationId and throws this IllegalStateException, because a duplicate key would silently overwrite a registration and break request matching.
Source
Thrown at oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/InMemoryReactiveClientRegistrationRepository.java:88
return Mono.justOrEmpty(this.clientIdToClientRegistration.get(registrationId));
}
/**
* Returns an {@code Iterator} of {@link ClientRegistration}.
* @return an {@code Iterator<ClientRegistration>}
*/
@Override
public Iterator<ClientRegistration> iterator() {
return this.clientIdToClientRegistration.values().iterator();
}
private static Map<String, ClientRegistration> toUnmodifiableConcurrentMap(List<ClientRegistration> registrations) {
Assert.notEmpty(registrations, "registrations cannot be null or empty");
ConcurrentHashMap<String, ClientRegistration> result = new ConcurrentHashMap<>();
for (ClientRegistration registration : registrations) {
Assert.notNull(registration, "no registration can be null");
if (result.containsKey(registration.getRegistrationId())) {
throw new IllegalStateException(String.format("Duplicate key %s", registration.getRegistrationId()));
}
result.put(registration.getRegistrationId(), registration);
}
return Collections.unmodifiableMap(result);
}
}
View on GitHub (pinned to 96852e8860)
Solutions
- Make every registrationId unique across all registrations passed to the constructor.
- If a bean-based config auto-generates registrations, exclude the duplicates instead of adding manual copies.
- Centralize registration creation (e.g. a @Bean returning the repository) so ids can't collide between config files and code.
- On failure, log each registration's getRegistrationId() before constructing to spot the duplicate quickly.
Example fix
// before
new InMemoryReactiveClientRegistrationRepository(List.of(
ClientRegistration.withRegistrationId("idp")...build(),
ClientRegistration.withRegistrationId("idp")...build())) // duplicate
// after
new InMemoryReactiveClientRegistrationRepository(List.of(
ClientRegistration.withRegistrationId("idp")...build(),
ClientRegistration.withRegistrationId("idp-2")...build())) Defensive patterns
Strategy: validation
Validate before calling
Set<String> seen = new HashSet<>();
for (ClientRegistration r : registrations) {
if (!seen.add(r.getRegistrationId())) throw new IllegalStateException("duplicate registrationId " + r.getRegistrationId());
} Try / catch
try { new InMemoryReactiveClientRegistrationRepository(registrations); } catch (IllegalStateException e) { if (e.getMessage().startsWith("Duplicate key")) { /* dedupe list and retry */ } throw e; } Prevention
- Generate registrationIds deterministically from tenant/issuer names
- Dedupe registrations by id before constructing the repository
- Add a unit test asserting unique registrationIds in config
When it happens
Trigger: new InMemoryReactiveClientRegistrationRepository(List<ClientRegistration>) where two registrations in the list share the same getRegistrationId() (checked in toUnmodifiableConcurrentMap).
Common situations: Loading registrations from application.yml via ClientRegistrationRepository beans and also declaring them manually; iterating over multiple issuer configs that all use the same registrationId placeholder; copying a registration and only changing clientId, forgetting the registrationId.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- No enum constant org.springframework.security.oauth2.client.
- server_error
- The issuer identifier (${issuer}) cannot be set when isMulti
- missing_signature_verifier
- missing_signature_verifier
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/b32c9339bc06d2f9.
Report an issue: GitHub.