twentyhq/twenty · warning · Error

File is not valid XML

Error message

File is not valid XML

What it means

Thrown by parseSAMLMetadataFromXMLFile (parseSAMLMetadataFromXMLFile.ts:69-71) when the DOMParser inserts a <parsererror> element, meaning the supplied string is not well-formed XML. The throw is caught at line 127 and returned as `{ success: false, reason: 'File is not valid XML' }` — callers never see it propagate.

Source

Thrown at packages/twenty-front/src/modules/settings/security/utils/parseSAMLMetadataFromXMLFile.ts:70

        const path = issue.path.join('.');
        return path.length > 0 ? `${path}: ${issue.message}` : issue.message;
      })
      .join('; ');
  }
  if (error instanceof Error) return error.message;
  return 'Unknown parsing error';
};

export const parseSAMLMetadataFromXMLFile = (
  xmlString: string,
):
  | { success: true; data: z.infer<typeof validator> }
  | { success: false; reason: string } => {
  try {
    const parser = new DOMParser();
    const xmlDoc = parser.parseFromString(xmlString, 'application/xml');
    if (xmlDoc.getElementsByTagName('parsererror').length > 0) {
      throw new Error('File is not valid XML');
    }

    const entityDescriptor = getByPrefixAndKey(xmlDoc, 'EntityDescriptor');
    if (!entityDescriptor)
      throw new Error('EntityDescriptor element is missing');

    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');

View on GitHub (pinned to 1f5dd2bbd2)

Solutions

  1. Provide a well-formed SAML 2.0 metadata XML file (validate with xmllint first).
  2. Download the metadata XML directly from the IdP rather than copy-pasting.
  3. Confirm the file is UTF-8 without BOM.
  4. Surface the returned `reason` to the user as a form validation error.
Defensive patterns

Strategy: validation

Validate before calling

// Validate XML well-formedness before calling the parser
const doc = new DOMParser().parseFromString(xmlString, 'application/xml');
if (doc.getElementsByTagName('parsererror').length > 0) {
  setError(t`Please upload a well-formed XML file`);
  return;
}

Type guard

const isWellFormedXml = (s: string): boolean =>
  new DOMParser().parseFromString(s, 'application/xml')
    .getElementsByTagName('parsererror').length === 0;

Try / catch

// The parser returns { success: false, reason } rather than throwing to callers:
const result = parseSAMLMetadataFromXMLFile(xmlString);
if (!result.success) {
  setFormError(result.reason);
  return;
}

Prevention

When it happens

Trigger: User uploads a SAML metadata file whose content fails XML parsing: not XML at all (JSON, plain text), malformed tags, unclosed elements, encoding issues. DOMParser.parseFromString with 'application/xml' embeds a parsererror element on failure, which the code detects.

Common situations: Uploading the wrong file (e.g. a certificate instead of metadata); copy-paste truncation; BOM or encoding mismatch; HTML content uploaded by mistake; partial file download.

Related errors


AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12). Data as JSON: /api/errors/5d6baf61d480ba28. Report an issue: GitHub.