{"record":{"id":"d73ba0e6e0c6a105","repo":"spring-projects/spring-security","slug":"failed-to-deserialize-payload-d73ba0","errorCode":null,"errorMessage":"Failed to deserialize payload","messagePattern":"Failed to deserialize payload","errorType":"exception","errorClass":"Saml2Exception","httpStatus":null,"severity":"error","filePath":"saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/OpenSaml5Template.java","lineNumber":160,"sourceCode":"\t@Override\n\tpublic <T extends XMLObject> T deserialize(InputStream serialized) {\n\t\ttry {\n\t\t\tParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();\n\t\t\tAssert.notNull(pool, \"ParserPool must be configured\");\n\t\t\tDocument document = pool.parse(serialized);\n\t\t\tElement element = document.getDocumentElement();\n\t\t\tUnmarshallerFactory factory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();\n\t\t\tUnmarshaller unmarshaller = factory.getUnmarshaller(element);\n\t\t\tif (unmarshaller == null) {\n\t\t\t\tthrow new Saml2Exception(\"Unsupported element of type \" + element.getTagName());\n\t\t\t}\n\t\t\treturn (T) unmarshaller.unmarshall(element);\n\t\t}\n\t\tcatch (Saml2Exception ex) {\n\t\t\tthrow ex;\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthrow new Saml2Exception(\"Failed to deserialize payload\", ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic OpenSaml5SerializationConfigurer serialize(XMLObject object) {\n\t\tMarshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);\n\t\tAssert.notNull(marshaller, \"Marshaller for \" + object.getElementQName() + \" must be configured\");\n\t\ttry {\n\t\t\treturn serialize(marshaller.marshall(object));\n\t\t}\n\t\tcatch (MarshallingException ex) {\n\t\t\tthrow new Saml2Exception(ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic OpenSaml5SerializationConfigurer serialize(Element element) {\n\t\treturn new OpenSaml5SerializationConfigurer(element);","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/OpenSaml5Template.java#L142-L178","documentation":"OpenSaml5Template.deserialize(String) wraps any non-Saml2Exception failure while parsing/unmarshalling the payload into Saml2Exception('Failed to deserialize payload') with the original as cause. This covers XML parse errors (malformed XML), IO errors from the ParserPool, and unmarshalling runtime exceptions.","triggerScenarios":"deserialize() receives input that cannot be parsed as XML (truncated/base64-decoding issues upstream, HTML error pages, invalid characters) or the unmarshaller itself fails mid-unmarshall.","commonSituations":"Sending the base64-encoded parameter without decoding it before calling deserialize; SAML POST binding payloads corrupted by URL-decoding; IdP returned an HTML error page instead of a SAML response; XML entity/prologue issues.","solutions":["Base64-decode the SAMLResponse/SAMLRequest parameter before deserializing","Check the cause chain (ex.getCause()) to distinguish XML syntax errors from unmarshalling errors","Inspect raw bytes of the payload for HTML error pages, truncation, or wrong encoding","Verify the message was not double URL-encoded/decoded through redirects"],"exampleFix":"// before\ntemplate.deserialize(request.getParameter(\"SAMLResponse\")); // still base64\n// after\nString xml = new String(Base64.getMimeDecoder().decode(request.getParameter(\"SAMLResponse\")), StandardCharsets.UTF_8);\ntemplate.deserialize(xml);","handlingStrategy":"try-catch","validationCode":"// pre-validate that payload decodes to well-formed XML\nbyte[] raw = Base64.getMimeDecoder().decode(samlParameter);\nDocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\ndbf.setNamespaceAware(true);\ndbf.newDocumentBuilder().parse(new InputSource(new StringReader(new String(raw, StandardCharsets.UTF_8))));","typeGuard":null,"tryCatchPattern":"try {\n    return template.deserialize(serialized);\n} catch (Saml2Exception ex) {\n    logger.warn(\"SAML payload deserialize failed\", ex.getCause());\n    throw new Saml2AuthenticationException(Saml2ErrorCodes.INVALID_RESPONSE, \"Malformed SAML payload\", ex);\n}","preventionTips":["Always Base64-decode POST-binding parameters before deserializing","Beware of double URL-encoding through redirects/proxies","Check for HTML error pages when the IdP misbehaves","Keep the cause chain when logging to see the XML parser's column/line info"],"tags":["saml2","deserialize","xml","parse-error","spring-security"],"backgroundTag":"xml-unmarshal-failed","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"}