spring-projects/spring-security · error · IllegalStateException

Embedded LDAP server is not provided

Error message

Embedded LDAP server is not provided

What it means

LdapServerBeanDefinitionParser.getRootBeanDefinition() selects the embedded container implementation by mode; only UnboundID is supported. If isUnboundIdEnabled(mode) is false (i.e. mode set to a non-UnboundID value like the removed ApacheDS), it throws IllegalStateException because no embedded server implementation is available.

Source

Thrown at config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java:175

		}
		ldapContainer.getConstructorArgumentValues().addGenericArgumentValue(ldifs);
		ldapContainer.getPropertyValues().addPropertyValue("port", getPort(element));
		if (parserContext.getRegistry().containsBeanDefinition(BeanIds.EMBEDDED_UNBOUNDID)) {
			parserContext.getReaderContext()
				.error("Only one embedded server bean is allowed per application context", element);
		}
		String beanId = resolveBeanId(mode);
		if (beanId != null) {
			parserContext.getRegistry().registerBeanDefinition(beanId, ldapContainer);
		}
		return (RootBeanDefinition) contextSource.getBeanDefinition();
	}

	private RootBeanDefinition getRootBeanDefinition(String mode) {
		if (isUnboundIdEnabled(mode)) {
			return new RootBeanDefinition(UNBOUNDID_CONTAINER_CLASSNAME, null, null);
		}
		throw new IllegalStateException("Embedded LDAP server is not provided");
	}

	private String resolveBeanId(String mode) {
		if (isUnboundIdEnabled(mode)) {
			return BeanIds.EMBEDDED_UNBOUNDID;
		}
		return null;
	}

	private boolean isUnboundIdEnabled(String mode) {
		return "unboundid".equals(mode) || unboundIdPresent;
	}

	private String getPort(Element element) {
		String port = element.getAttribute(ATT_PORT);
		return (StringUtils.hasText(port) ? port : getDefaultPort());
	}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Remove the mode attribute or set it to the UnboundID mode so the UnboundID container bean definition is used.
  2. Add the unboundid-ldapsdk dependency and drop legacy ApacheDS references.
  3. Point <ldap-server/> at an external server (url attribute) instead of embedded mode.

Example fix

// before
<security:ldap-server mode="apacheds" ldif="classpath:data.ldif"/>

// after
<security:ldap-server ldif="classpath:data.ldif"/>
Defensive patterns

Strategy: validation

Validate before calling

String mode = element.getAttribute("mode");
if (mode != null && !mode.isEmpty() && !"unboundid".equals(mode)) {
  throw new IllegalArgumentException("Unsupported embedded LDAP mode: " + mode + "; use UnboundID");
}

Try / catch

try { parser.parse(element, parserContext); }
catch (IllegalStateException e) {
  if (e.getMessage().contains("Embedded LDAP server is not provided")) dropLegacyModeAttribute();
}

Prevention

When it happens

Trigger: <ldap-server/> with a mode attribute value other than the UnboundID-supported one (e.g. legacy mode="apacheds"), causing isUnboundIdEnabled() to return false during bean definition parsing.

Common situations: Migrating from Spring Security 3.x where ApacheDS embedded mode existed; keeping mode="apacheds" after upgrade; typos in the mode attribute.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/7673b9ced5c6e331. Report an issue: GitHub.