Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions YoutubeExplode/Playlists/PlaylistClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using YoutubeExplode.Bridge;
using YoutubeExplode.Common;
using YoutubeExplode.Exceptions;
using YoutubeExplode.Videos;
Expand Down Expand Up @@ -83,13 +84,22 @@ public async IAsyncEnumerable<Batch<PlaylistVideo>> GetVideoBatchesAsync(

do
{
var response = await _controller.GetPlaylistNextResponseAsync(
playlistId,
lastVideoId,
lastVideoIndex,
visitorData,
cancellationToken
);
PlaylistNextResponse response;
try
{
response = await _controller.GetPlaylistNextResponseAsync(
playlistId,
lastVideoId,
lastVideoIndex,
visitorData,
cancellationToken
);
}
catch (PlaylistUnavailableException)
{
// Stop enumeration if the playlist becomes unavailable
yield break;
Comment on lines +100 to +101
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we try the next batch still, until it's empty?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!
I already tried that with jumping techniques instead of brute forcing every index, but it always misses some videos.

I can give it another round of trial.

But for this pr, it just returns with the available ones until an unavailable batch comes in.

}

var videos = new List<PlaylistVideo>();

Expand Down
7 changes: 6 additions & 1 deletion YoutubeExplode/Playlists/PlaylistController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Net.Http;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using YoutubeExplode.Bridge;
Expand Down Expand Up @@ -126,6 +127,10 @@ await http.GetAsync(
continue;
}

// If the response contains videos, proceed with them even if the playlist is marked unavailable
if (playlistResponse.Videos.Any())
Comment on lines +130 to +131
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new logic bypasses the retry mechanism when videos are present. If playlistResponse.Videos.Any() returns true, the method returns immediately without decrementing retriesRemaining, which could mask transient errors. Consider checking if videos exist before entering the retry logic, or ensure this check only applies on the final retry attempt.

Suggested change
// If the response contains videos, proceed with them even if the playlist is marked unavailable
if (playlistResponse.Videos.Any())
// If the response contains videos, proceed with them even if the playlist is marked unavailable,
// but only on the final retry attempt.
if (retriesRemaining == 0 && playlistResponse.Videos.Any())

Copilot uses AI. Check for mistakes.
return playlistResponse;

throw new PlaylistUnavailableException(
$"Playlist '{playlistId}' is not available."
);
Expand Down
Loading