twentyhq/twenty · error · Error
X509Certificate is missing or empty
Error message
X509Certificate is missing or empty
What it means
Thrown when <X509Data> exists but either has no <X509Certificate> child, or the child's textContent is empty after trimming. The certificate text is the base64 DER blob Twenty uses as the IdP signing cert.
Source
Thrown at packages/twenty-front/src/modules/settings/security/utils/parseSAMLMetadataFromXMLFile.ts:95
const IDPSSODescriptor = getByPrefixAndKey(xmlDoc, 'IDPSSODescriptor');
if (!IDPSSODescriptor)
throw new Error('IDPSSODescriptor element is missing');
const keyDescriptors = getByPrefixAndKey(IDPSSODescriptor, 'KeyDescriptor');
if (!keyDescriptors) throw new Error('KeyDescriptor element is missing');
const keyInfo = getByPrefixAndKey(keyDescriptors, 'KeyInfo');
if (!keyInfo) throw new Error('KeyInfo element is missing');
const x509Data = getByPrefixAndKey(keyInfo, 'X509Data');
if (!x509Data) throw new Error('X509Data element is missing');
const x509Certificate = getByPrefixAndKey(
x509Data,
'X509Certificate',
)?.textContent?.trim();
if (!x509Certificate)
throw new Error('X509Certificate is missing or empty');
const singleSignOnServices = getAllByPrefixAndKey(
IDPSSODescriptor,
'SingleSignOnService',
).map((service) => ({
binding: service.getAttribute('Binding'),
location: service.getAttribute('Location'),
}));
// Prefer HTTP-Redirect (the default authnRequestBinding on the SP side),
// fall back to HTTP-POST since both are valid SAML 2.0 bindings and many
// IdPs (e.g. JumpCloud) only advertise HTTP-POST.
const ssoUrl =
singleSignOnServices.find((s) => s.binding === HTTP_REDIRECT_BINDING)
?.location ??
singleSignOnServices.find((s) => s.binding === HTTP_POST_BINDING)
?.location;
View on GitHub (pinned to 1f5dd2bbd2)
Solutions
- Open the XML and confirm <X509Certificate> has non-empty base64 text content.
- Re-export metadata from the IdP so the cert body is intact.
- Validate the cert string decodes as valid base64 before uploading.
Example fix
// before: <ds:X509Certificate></ds:X509Certificate> // after: <ds:X509Certificate>MIIDAzCCAeugAwIBAgIU...</ds:X509Certificate>
Defensive patterns
Strategy: validation
Validate before calling
const extractCert = (xml: string): string | null => {
const m = xml.match(/<[^>]*X509Certificate[^>]*>([\s\S]*?)<\/[^>]*X509Certificate>/);
const body = m?.[1]?.trim();
return body ? body : null;
};
// guard: if (!extractCert(xml)) showFormError('certificate missing'); Type guard
const isNonEmptyCertificate = (cert: string | undefined | null): cert is string => typeof cert === 'string' && cert.trim().length > 0 && /^[A-Za-z0-9+/=\s]+$/.test(cert);
Try / catch
const res = parseSAMLMetadataFromXMLFile(xml);
if (!res.success) {
// res.reason may be 'X509Certificate is missing or empty'
return;
} Prevention
- Validate the cert body is non-empty base64 before upload.
- Re-export metadata after cert rotation to avoid placeholder/empty elements.
When it happens
Trigger: X509Certificate element is missing entirely, is self-closing, or its text content is whitespace/empty. A placeholder metadata file was uploaded.
Common situations: Test/stub metadata with an empty cert. Copy-paste dropped the long base64 string. IdP certificate rotation left a temporarily empty element.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- KeyDescriptor element is missing
- KeyInfo element is missing
- X509Data element is missing
- No SingleSignOnService with HTTP-Redirect or HTTP-POST bindi
- File is not valid XML
AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12).
Data as JSON: /api/errors/a271f59884b37bb8.
Report an issue: GitHub.