{"record":{"id":"808f7a248d092c9c","repo":"twentyhq/twenty","slug":"keyinfo-element-is-missing","errorCode":null,"errorMessage":"KeyInfo element is missing","messagePattern":"KeyInfo element is missing","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/twenty-front/src/modules/settings/security/utils/parseSAMLMetadataFromXMLFile.ts","lineNumber":85,"sourceCode":"    const parser = new DOMParser();\n    const xmlDoc = parser.parseFromString(xmlString, 'application/xml');\n    if (xmlDoc.getElementsByTagName('parsererror').length > 0) {\n      throw new Error('File is not valid XML');\n    }\n\n    const entityDescriptor = getByPrefixAndKey(xmlDoc, 'EntityDescriptor');\n    if (!entityDescriptor)\n      throw new Error('EntityDescriptor element is missing');\n\n    const IDPSSODescriptor = getByPrefixAndKey(xmlDoc, 'IDPSSODescriptor');\n    if (!IDPSSODescriptor)\n      throw new Error('IDPSSODescriptor element is missing');\n\n    const keyDescriptors = getByPrefixAndKey(IDPSSODescriptor, 'KeyDescriptor');\n    if (!keyDescriptors) throw new Error('KeyDescriptor element is missing');\n\n    const keyInfo = getByPrefixAndKey(keyDescriptors, 'KeyInfo');\n    if (!keyInfo) throw new Error('KeyInfo element is missing');\n\n    const x509Data = getByPrefixAndKey(keyInfo, 'X509Data');\n    if (!x509Data) throw new Error('X509Data element is missing');\n\n    const x509Certificate = getByPrefixAndKey(\n      x509Data,\n      'X509Certificate',\n    )?.textContent?.trim();\n    if (!x509Certificate)\n      throw new Error('X509Certificate is missing or empty');\n\n    const singleSignOnServices = getAllByPrefixAndKey(\n      IDPSSODescriptor,\n      'SingleSignOnService',\n    ).map((service) => ({\n      binding: service.getAttribute('Binding'),\n      location: service.getAttribute('Location'),\n    }));","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/twentyhq/twenty/blob/1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6/packages/twenty-front/src/modules/settings/security/utils/parseSAMLMetadataFromXMLFile.ts#L67-L103","documentation":"Thrown when a KeyDescriptor element was found inside IDPSSODescriptor but it has no XMLDSig <KeyInfo> child element. KeyInfo is the standard wrapper (under the ds/dsig namespace) holding the <X509Data>. Without it the parser cannot reach the certificate.","triggerScenarios":"KeyDescriptor exists but is self-closing or empty, or only carries an encryption role with no KeyInfo. KeyInfo is present but under a namespace prefix outside the md/ns0/ns2/dsig/ds allowlist, so getByPrefixAndKey returns undefined.","commonSituations":"IdP metadata where only an encryption KeyDescriptor is published and the signing one is stripped. Copy-paste of metadata truncates the KeyInfo subtree. Namespace prefix mismatch on the dsig portion.","solutions":["Inspect the KeyDescriptor in the uploaded XML and confirm a <KeyInfo> child is present.","Ensure the KeyInfo element uses the ds/dsig (or md/ns0/ns2) prefix that the parser recognizes.","Re-download the metadata XML directly from the IdP to avoid truncation."],"exampleFix":"// before: <md:KeyDescriptor use=\"encryption\"><xenc:EncryptionMethod .../></md:KeyDescriptor>  (no KeyInfo)\n// after:  <md:KeyDescriptor use=\"signing\"><ds:KeyInfo><ds:X509Data>...</ds:X509Data></ds:KeyInfo></md:KeyDescriptor>","handlingStrategy":"validation","validationCode":"const hasKeyInfo = (xml: string): boolean => {\n  const doc = new DOMParser().parseFromString(xml, 'application/xml');\n  return ['md', 'ns0', 'ns2', 'dsig', 'ds', ''].some((p) =>\n    doc.getElementsByTagName(p ? `${p}:KeyInfo` : 'KeyInfo').length > 0);\n};","typeGuard":"const metadataHasSigningKeyInfo = (xml: string): boolean =>\n  /<[^>]*KeyDescriptor[^>]*use=[\"']signing[\"'][\\s\\S]*?<[^>]*KeyInfo[\\s\\S]*?<\\/[^>]*KeyDescriptor>/.test(xml);","tryCatchPattern":"const res = parseSAMLMetadataFromXMLFile(xml);\nif (!res.success) {\n  setFieldError('metadataFile', res.reason); // 'KeyInfo element is missing'\n  return;\n}","preventionTips":["Inspect the KeyDescriptor for use=\"signing\"; some IdPs only emit encryption KeyDescriptors.","Confirm the ds/dsig prefix is recognized by the parser.","Re-download metadata from the IdP to avoid truncation."],"tags":["saml","sso","xml","enterprise","validation"],"backgroundTag":null,"analyzedSha":"1f5dd2bbd2a8da3419c8cfd52dd545c0024df1a6","analyzedAt":"2026-08-12T15:37:27.593Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}