Skip to content

fix(youtube): clarify missing player response errors#71

Open
Priveetee wants to merge 1 commit into
InfinityLoop1308:mainfrom
Priveetee:fix-youtube-coppa-streams
Open

fix(youtube): clarify missing player response errors#71
Priveetee wants to merge 1 commit into
InfinityLoop1308:mainfrom
Priveetee:fix-youtube-coppa-streams

Conversation

@Priveetee

@Priveetee Priveetee commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Context from TypeType issue:

Priveetee/TypeType#72

Related SABR work:

Related PipePipe issue:

Summary

TypeType issue #72 surfaced a YouTube extraction failure where the frontend received:

Cannot invoke "com.grack.nanojson.JsonObject.getObject(String)" because "this.playerResponse" is null

I reproduced the null playerResponse path locally by delaying the player response, then checked the affected Made for Kids / COPPA examples to understand the underlying playback failure.

This PR does not fix playback for those videos. That appears to be in the SABR / login-required area already being explored in #69.

This PR only makes the failure explicit and user-actionable instead of surfacing as a null playerResponse crash.

Problem

YoutubeStreamExtractor.onFetchPage() currently skips playability checks when playerResponse == null.

If no usable player response was fetched, fetchPage() can still return, and later getters such as getName() assume playerResponse exists.

That turns a YouTube extraction failure into a NullPointerException, which makes the real cause harder to understand and harder to surface to users.

Findings

Tested examples:

https://www.youtube.com/watch?v=8KtnrtHRiCg
https://www.youtube.com/watch?v=mZuTUz5ilOs

Observed locally:

ANDROID_VR: UNPLAYABLE, no streamingData
WEB: UNPLAYABLE, no streamingData
ANDROID / WEB_EMBED: streamingData present, but no usable stream URLs

There is a possible workaround using the Safari player response. In local testing it returned progressive streams for the affected videos.

I am intentionally not adding that fallback here because I do not like the tradeoff: it is fragile, it changes stream selection behavior, and it would paper over the actual SABR-related issue instead of fixing it.

The long-term fix is likely in the SABR area, which is already being explored in #69. Until then, affected users should try logging in if they need an immediate workaround.

Changes

  • Throw a normal extraction exception when no usable YouTube player response was fetched.
  • Include Try logging in. in the error shown for this failure path.
  • Include Try logging in. when YouTube returns the page needs to be reloaded error.
  • Avoid exposing the internal null playerResponse crash to users.

Validation

  • git diff --check
  • ./gradlew :extractor:compileJava --no-daemon
  • Reproduced the original null playerResponse crash with a delayed player response.
  • Verified the same path now returns:
Could not fetch a usable YouTube player response. Try logging in.
  • Verified the real COPPA sample now returns:
The page needs to be reloaded. Try logging in.
  • Verified a normal YouTube video still extracts streams:
https://www.youtube.com/watch?v=dQw4w9WgXcQ

audio=4
video=1
videoOnly=18
errors=0

Notes

This does not implement SABR playback and does not add a Safari fallback.

The affected COPPA/SABR cases still require SABR support or login/tokens. This PR only improves the failure mode and tells users to try logging in instead of surfacing an internal null crash.

@InfinityLoop1308

Copy link
Copy Markdown
Owner

Can you take a look at these two? They have the same error but seem not the COPPA case.

@Priveetee

Copy link
Copy Markdown
Contributor Author

Yep of course, I'm gonna take a look at them ☺️

@Priveetee

Copy link
Copy Markdown
Contributor Author

Yep, I took a look at both :)

For #2456, the stack trace goes through YoutubeStreamExtractor.getName() with playerResponse == null, so it looks like the same failure mode fixed by this PR.

For #2482, it is related but not exactly the same case. The reported video is:

https://www.youtube.com/watch?v=JfM95tV_r2Y

With normal extraction it works locally.

When I simulate a slow/missing WEB player metadata response, the stream extraction still succeeds, but optional metadata extraction can produce errors because playerMicroFormatRenderer is null. The affected getters are around upload date / privacy / category / start position.

So my current read is:

#2456 -> likely covered by this PR
#2482 -> similar async/race class, but different missing field

This PR currently only handles the playerResponse == null crash. I can either keep it scoped like that, or extend it to also make the optional playerMicroFormatRenderer getters fail gracefully when WEB metadata is missing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants