{"record":{"id":"7d07af0baa53c0a4","repo":"ytdl-org/youtube-dl","slug":"invalid-dfxp-ttml-subtitle","errorCode":null,"errorMessage":"Invalid dfxp/TTML subtitle","messagePattern":"Invalid dfxp/TTML subtitle","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"youtube_dl/utils.py","lineNumber":5083,"sourceCode":"        def close(self):\n            return self._out.strip()\n\n    def parse_node(node):\n        target = TTMLPElementParser()\n        parser = xml.etree.ElementTree.XMLParser(target=target)\n        parser.feed(xml.etree.ElementTree.tostring(node))\n        return parser.close()\n\n    for k, v in LEGACY_NAMESPACES:\n        for ns in v:\n            dfxp_data = dfxp_data.replace(ns, k)\n\n    dfxp = compat_etree_fromstring(dfxp_data)\n    out = []\n    paras = dfxp.findall(_x('.//ttml:p')) or dfxp.findall('.//p')\n\n    if not paras:\n        raise ValueError('Invalid dfxp/TTML subtitle')\n\n    repeat = False\n    while True:\n        for style in dfxp.findall(_x('.//ttml:style')):\n            style_id = style.get('id') or style.get(_x('xml:id'))\n            if not style_id:\n                continue\n            parent_style_id = style.get('style')\n            if parent_style_id:\n                if parent_style_id not in styles:\n                    repeat = True\n                    continue\n                styles[style_id] = styles[parent_style_id].copy()\n            for prop in SUPPORTED_STYLING:\n                prop_val = style.get(_x('tts:' + prop))\n                if prop_val:\n                    styles.setdefault(style_id, {})[prop] = prop_val\n        if repeat:","sourceCodeStart":5065,"sourceCodeEnd":5101,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/utils.py#L5065-L5101","documentation":"Raised by dfxp2srt() in youtube_dl.utils after parsing subtitle XML: it looks for <tt:p>/<ttml:p> (or legacy <p>) paragraph elements anywhere in the document and finds none, so there is no subtitle content to convert to SRT. It signals structurally valid XML that is not a recognizable DFXP/TTML subtitle document.","triggerScenarios":"Calling dfxp2srt(dfxp_data) where dfxp_data is XML lacking any p elements: an HTML error page saved as .ttml, a ttml file whose paragraphs use a different namespace not covered by LEGACY_NAMESPACES substitution, an empty <tt/> skeleton, or binary/garbage data that ElementTree still parsed (or that became an empty root after namespace mangling).","commonSituations":"A subtitle URL returns an error page or login wall instead of TTML; a site renames subtitle namespaces or serves WebVTT/JSON mislabeled as ttml; downloading subtitles with --write-sub --convert-subs srt for a format the converter does not recognize.","solutions":["Inspect the downloaded .ttml file to confirm it actually contains <p> subtitle elements.","If the content is another format (vtt/srt/json), convert with the appropriate path or keep it unconverted (--convert-subs not set to srt).","If namespaces changed, extend LEGACY_NAMESPACES in youtube_dl/utils.py to map the new namespace to ttml.","Re-fetch the subtitle URL manually (browser or curl) to check for HTML error pages; fix auth/cookies if that is the cause."],"exampleFix":"# before\nfrom youtube_dl.utils import dfxp2srt\nsrt = dfxp2srt(xml_text)  # ValueError: Invalid dfxp/TTML subtitle — no <p> elements\n\n# after\nimport xml.etree.ElementTree as ET\nfrom youtube_dl.utils import dfxp2srt\nroot = ET.fromstring(xml_text)\nif not (root.findall('.//{http://www.w3.org/ns/ttml}p') or root.findall('.//p')):\n    raise ValueError('source is not a TTML subtitle document; keeping original')\nsrt = dfxp2srt(xml_text)","handlingStrategy":"validation","validationCode":"import xml.etree.ElementTree as ET\n\ndef looks_like_ttml(data):\n    try:\n        root = ET.fromstring(data)\n    except ET.ParseError:\n        return False\n    return bool(root.findall('.//{http://www.w3.org/ns/ttml}p') or root.findall('.//p'))\n\n# call before dfxp2srt:\n# if not looks_like_ttml(data): keep original subtitle file","typeGuard":null,"tryCatchPattern":"from youtube_dl.utils import dfxp2srt, XAttrUnavailableError  # ValueError is not custom — catch broadly\ntry:\n    srt = dfxp2srt(ttml_bytes)\nexcept ValueError:\n    # keep the original subtitle file, do not convert\n    srt = None","preventionTips":["Check the subtitle body starts with <tt and contains p elements before converting.","Verify the subtitle URL returns TTML, not an HTML error page (check content-type).","When a site changes TTML namespaces, update LEGACY_NAMESPACES rather than forcing conversion."],"tags":["subtitles","ttml","dfxp","parsing"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}