apereo/cas · info
Existing SOAP Envelope Body already contained children
Error message
Existing SOAP Envelope Body already contained children
What it means
CasHttpSoap11Encoder.buildAndStoreSOAPMessage() constructs a SOAP 1.1 Envelope with a single Body and stores the outgoing message. If the freshly built Body already contains unknown XMLObjects, it logs this warning before appending the payload, indicating leftover/pre-existing children in the Body that may yield an unexpected SOAP message structure. It is defensive logging rather than a hard failure.
Solutions
- Create a fresh CasHttpSoap11Encoder (and SOAP message context) per request instead of reusing instances
- Verify the payload is added exactly once and no earlier code populated the Body
- Inspect the produced SOAP envelope to confirm only the intended payload is present
- If the warning is benign in your flow, ensure the added payload ordering still satisfies the SAML binding spec
Example fix
// before: shared encoder field private final CasHttpSoap11Encoder encoder = new CasHttpSoap11Encoder(...); // after: per-use instance val encoder = new CasHttpSoap11Encoder(builderFactory); encoder.buildAndStoreSOAPMessage(payload);
Defensive patterns
Strategy: type-guard
Validate before calling
// ensure a clean encoder/message per send assert encoderNotReused && body.getUnknownXMLObjects().isEmpty();
Type guard
function bodyIsEmpty(body) { return body.getUnknownXMLObjects().isEmpty(); } Try / catch
if (!body.getUnknownXMLObjects().isEmpty()) {
log.warn('SOAP body pre-populated; constructing fresh envelope');
encoder = newEncoder();
} Prevention
- Instantiate a new SOAP encoder per message
- Do not cache OpenSAML objects across requests
- Verify the generated envelope contains exactly one payload
When it happens
Trigger: Reusing an encoder or SOAP object tree where the Body element was previously populated (e.g. the encoder instance is reused across requests or the OpenSAML builder returns a cached/shared Body).
Common situations: Custom SAML SOAP encoding code reusing a single encoder instance for multiple messages; incorrectly wiring the OpenSAML builderFactory so it returns shared objects; embedding the encoder in a singleton Spring bean with state carried between calls.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- SAML2 attribute query profile is not enabled
- Encoded password is null.
- No Certificates provided
- Public and private keys do not match
- Configuration element indicated an entityCertificate, but…
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/187db786ac15c07b.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-saml-core-api/src/main/java/org/apereo/cas/support/saml/util/CasHttpSoap11Encoder.java:45
@Override
protected void buildAndStoreSOAPMessage(
@NonNull
final XMLObject payload) {
val builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory();
val envBuilder =
(SOAPObjectBuilder<Envelope>) builderFactory.getBuilder(Envelope.DEFAULT_ELEMENT_NAME);
val envelope = envBuilder.buildObject(
SOAPConstants.SOAP11_NS, Envelope.DEFAULT_ELEMENT_LOCAL_NAME, OPENSAML_11_SOAP_NS_PREFIX);
val bodyBuilder =
(SOAPObjectBuilder<Body>) builderFactory.getBuilder(Body.DEFAULT_ELEMENT_NAME);
val body = bodyBuilder.buildObject(
SOAPConstants.SOAP11_NS, Body.DEFAULT_ELEMENT_LOCAL_NAME, OPENSAML_11_SOAP_NS_PREFIX);
if (!body.getUnknownXMLObjects().isEmpty()) {
LOGGER.warn("Existing SOAP Envelope Body already contained children");
}
body.getUnknownXMLObjects().add(payload);
envelope.setBody(body);
this.storeSOAPEnvelope(envelope);
}
}
View on GitHub (pinned to e7288fc434)