ytdl-org/youtube-dl · error · ValueError
Invalid dfxp/TTML subtitle
Error message
Invalid dfxp/TTML subtitle
What it means
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.
Source
Thrown at youtube_dl/utils.py:5083
def close(self):
return self._out.strip()
def parse_node(node):
target = TTMLPElementParser()
parser = xml.etree.ElementTree.XMLParser(target=target)
parser.feed(xml.etree.ElementTree.tostring(node))
return parser.close()
for k, v in LEGACY_NAMESPACES:
for ns in v:
dfxp_data = dfxp_data.replace(ns, k)
dfxp = compat_etree_fromstring(dfxp_data)
out = []
paras = dfxp.findall(_x('.//ttml:p')) or dfxp.findall('.//p')
if not paras:
raise ValueError('Invalid dfxp/TTML subtitle')
repeat = False
while True:
for style in dfxp.findall(_x('.//ttml:style')):
style_id = style.get('id') or style.get(_x('xml:id'))
if not style_id:
continue
parent_style_id = style.get('style')
if parent_style_id:
if parent_style_id not in styles:
repeat = True
continue
styles[style_id] = styles[parent_style_id].copy()
for prop in SUPPORTED_STYLING:
prop_val = style.get(_x('tts:' + prop))
if prop_val:
styles.setdefault(style_id, {})[prop] = prop_val
if repeat:View on GitHub (pinned to 956b8c5855)
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.
Example fix
# before
from youtube_dl.utils import dfxp2srt
srt = dfxp2srt(xml_text) # ValueError: Invalid dfxp/TTML subtitle — no <p> elements
# after
import xml.etree.ElementTree as ET
from youtube_dl.utils import dfxp2srt
root = ET.fromstring(xml_text)
if not (root.findall('.//{http://www.w3.org/ns/ttml}p') or root.findall('.//p')):
raise ValueError('source is not a TTML subtitle document; keeping original')
srt = dfxp2srt(xml_text) Defensive patterns
Strategy: validation
Validate before calling
import xml.etree.ElementTree as ET
def looks_like_ttml(data):
try:
root = ET.fromstring(data)
except ET.ParseError:
return False
return bool(root.findall('.//{http://www.w3.org/ns/ttml}p') or root.findall('.//p'))
# call before dfxp2srt:
# if not looks_like_ttml(data): keep original subtitle file Try / catch
from youtube_dl.utils import dfxp2srt, XAttrUnavailableError # ValueError is not custom — catch broadly
try:
srt = dfxp2srt(ttml_bytes)
except ValueError:
# keep the original subtitle file, do not convert
srt = None Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/7d07af0baa53c0a4.
Report an issue: GitHub.