spring-projects/spring-security · error · Saml2Exception

Failed to deserialize payload

Error message

Failed to deserialize payload

What it means

The metadata-package copy of OpenSaml5Template.deserialize(): any non-Saml2Exception failure while parsing or unmarshalling the payload (SAX parse errors, schema violations, ParserPool problems) is wrapped in this Saml2Exception with the root cause attached. The input could not be converted to an OpenSAML XMLObject.

Source

Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/metadata/OpenSaml5Template.java:160

	@Override
	public <T extends XMLObject> T deserialize(InputStream serialized) {
		try {
			ParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();
			Assert.notNull(pool, "ParserPool must be configured");
			Document document = pool.parse(serialized);
			Element element = document.getDocumentElement();
			UnmarshallerFactory factory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
			Unmarshaller unmarshaller = factory.getUnmarshaller(element);
			if (unmarshaller == null) {
				throw new Saml2Exception("Unsupported element of type " + element.getTagName());
			}
			return (T) unmarshaller.unmarshall(element);
		}
		catch (Saml2Exception ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new Saml2Exception("Failed to deserialize payload", ex);
		}
	}

	@Override
	public OpenSaml5SerializationConfigurer serialize(XMLObject object) {
		Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
		Assert.notNull(marshaller, "Marshaller for " + object.getElementQName() + " must be configured");
		try {
			return serialize(marshaller.marshall(object));
		}
		catch (MarshallingException ex) {
			throw new Saml2Exception(ex);
		}
	}

	@Override
	public OpenSaml5SerializationConfigurer serialize(Element element) {
		return new OpenSaml5SerializationConfigurer(element);

View on GitHub (pinned to 96852e8860)

Solutions

  1. Log ex.getCause() (usually a SAXParseException with line/column) to locate the malformed part of the document.
  2. Confirm the metadata body is complete and correctly encoded (UTF-8); check for proxy/CDN truncation and Content-Length mismatches.
  3. Re-fetch the metadata and compare — transient truncation is fixed by retry with backoff.
  4. Validate the document against the SAML metadata schema and raise the issue with the IdP if it emits invalid XML.

Example fix

// before
EntityDescriptor ed = template.deserialize(truncatedBody);
// Saml2Exception: Failed to deserialize payload
// after
try {
    EntityDescriptor ed = template.deserialize(body);
} catch (Saml2Exception ex) {
    throw new Saml2Exception("Invalid metadata from " + metadataUrl + ": " + ex.getCause().getMessage(), ex);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (body == null || body.trim().length() == 0) {
    throw new IllegalStateException("Metadata body is empty");
}
if (expectedLength > 0 && body.length() < expectedLength) {
    throw new IllegalStateException("Metadata body truncated (" + body.length() + " of " + expectedLength + " bytes)");
}

Try / catch

try {
    EntityDescriptor ed = template.deserialize(body);
} catch (Saml2Exception ex) {
    Throwable cause = ex.getCause();
    logger.warn("Metadata parse failed at {}", cause == null ? "unknown" : cause.getMessage());
    throw new Saml2Exception("Invalid metadata from endpoint", ex);
}

Prevention

When it happens

Trigger: Calling OpenSaml5Template.deserialize(String) with malformed or schema-invalid metadata XML — truncated documents, invalid XML characters, encoding mismatch, duplicate IDs, or an unparseable body returned by a metadata endpoint.

Common situations: Metadata endpoints behind proxies/CDNs returning partial or garbage bodies; metadata fetched with wrong charset handling; IdP emitting invalid XML (unescaped '&', malformed entities); network truncation of large metadata files.

Related errors


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