yuliskov/SmartTube · error · IllegalStateException
Malformed mpd file: ${mpdContent}
Error message
Malformed mpd file:
${mpdContent} What it means
getManifest(Uri, InputStream) parses already-fetched mpd bytes with StaticDashManifestParser; an IOException from the parser (malformed XML, empty or truncated body) is rethrown as IllegalStateException embedding the entire mpd content for diagnosis. When the 'mpd' is actually an HTML error page, the exception text makes that obvious — which is the point of including it.
Source
Thrown at common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/ExoMediaSourceFactory.java:260
}
private SabrManifest getSabrManifest(MediaItemFormatInfo formatInfo) {
SabrManifestParser parser = new SabrManifestParser();
return parser.parse(formatInfo);
}
private DashManifest getManifest(MediaItemFormatInfo formatInfo) {
DashManifestParser2 parser = new DashManifestParser2();
return parser.parse(formatInfo);
}
private DashManifest getManifest(Uri uri, InputStream mpdContent) {
DashManifestParser parser = new StaticDashManifestParser();
DashManifest result;
try {
result = parser.parse(uri, mpdContent);
} catch (IOException e) {
throw new IllegalStateException("Malformed mpd file:\n" + mpdContent, e);
}
return result;
}
private DashManifest getManifest(Uri uri, String mpdContent) {
DashManifestParser parser = new StaticDashManifestParser();
DashManifest result;
try {
result = parser.parse(uri, FileHelpers.toStream(mpdContent));
} catch (IOException e) {
throw new IllegalStateException("Malformed mpd file:\n" + mpdContent, e);
}
return result;
}
/**
* Use OkHttp for networking
*/
View on GitHub (pinned to 3de8d90593)
Solutions
- Read the embedded content prefix in the exception message — '<MPD' vs '<html' distinguishes a parser bug from a bad response
- Re-fetch the format info / refresh the URL and rebuild the media source before retrying
- If the body is HTML, investigate middleboxes (proxy, VPN, DNS filtering) rather than the parser
- Treat it as a parser defect only when the content is well-formed mpd and still fails
Example fix
// before
DashManifest m = parser.parse(uri, mpdStream); // IOException -> IllegalStateException
// after
if (mpdContent == null || !mpdContent.trim().startsWith("<")) {
throw new IllegalStateException("URL did not return a manifest (likely an error page)");
}
DashManifest m = parser.parse(uri, FileHelpers.toStream(mpdContent)); Defensive patterns
Strategy: validation
Validate before calling
String body = readFully(stream);
if (body == null || !body.trim().startsWith("<")) {
// not a manifest: refresh the url / format info instead of parsing
return refreshAndRetry();
}
DashManifest manifest = parser.parse(uri, FileHelpers.toStream(body)); Try / catch
try {
return getManifest(uri, stream);
} catch (IllegalStateException e) {
// message embeds the body: inspect prefix, then re-fetch manifest and retry once
} Prevention
- Sanity-check that fetched manifest bodies start with '<MPD' before parsing
- Refresh signed/expiring URLs before building a media source from cached content
- Treat HTML bodies as a network/middlebox signal, not a parser defect
When it happens
Trigger: The fetched URL returned an HTML error/block page instead of DASH xml (expired signed URL, geo-block, proxy interference); the body was truncated mid-transfer; the InputStream is empty because the upstream fetch already failed.
Common situations: Expired stream URLs from YouTube-style backends; VPN/ISP-injected pages; ad-blocking or AFR proxy rewriting responses; retrying playback with stale cached format info.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
AI-assisted analysis of yuliskov/SmartTube@3de8d90593 (2026-08-22).
Data as JSON: /api/errors/0271519999e9dcb5.
Report an issue: GitHub.