Common Failure Scenarios When Downloading from YouTube Music: How SpotifySaver Handles Errors

SpotifySaver implements a fail-soft architecture that catches network errors, API failures, and missing metadata during YouTube Music downloads, logging issues and returning clean status flags without corrupting your music library.

When downloading music from YouTube Music, users encounter various failure scenarios ranging from network interruptions to unavailable tracks. The open-source tool SpotifySaver (gabrielbaute/spotify-saver) addresses these challenges through its YouTubeDownloader class, implementing comprehensive error handling for common failure scenarios when downloading from YouTube Music.

YouTube Music Search and API Failure Scenarios

The YoutubeMusicSearcher.search_track() method in spotifysaver/services/youtube_api.py implements multiple search strategies—exact matching, album-context searching, and fuzzy matching—to locate tracks. When all strategies fail to find a match, the method returns None at lines 94-100, triggering an error log entry: self.logger.error(f"No match found for: {track.name}").

The downloader aborts the specific track download and returns (None, None) to the caller, allowing the application to skip the missing track and continue with remaining downloads without crashing.

Transient API Errors and Retry Logic

Network instability and rate limiting can trigger YouTubeAPIError, AlbumNotFoundError, or InvalidResultError during search operations. The search_track() method wraps API calls in a retry loop (default 3 attempts) as shown in youtube_api.py lines 40-55.

Each caught exception generates a warning log, and the loop continues until success or exhaustion. If all retries fail, the method logs a final error and returns None, ensuring the application never hangs on a single network hiccup.

Download and Network Failure Handling

yt-dlp Execution Failures

The actual audio extraction relies on yt-dlp, which can fail due to HTTP errors, unavailable fragments, or geographic restrictions. In spotifysaver/downloader/youtube_downloader.py, the download_track() method (lines 140-166) wraps the yt-dlp subprocess call in a comprehensive try … except block.

Any exception during execution triggers immediate error logging and initiates cleanup protocols.

Partial File Cleanup

To prevent corrupted files from polluting the music library, the error handler in youtube_downloader.py lines 140-166 explicitly removes partially-written files using output_path.unlink() before returning (None, None). This atomic approach ensures that only complete, valid audio files remain in the destination directory, maintaining library integrity even when downloads fail mid-stream.

Metadata and Asset Failure Resilience

Missing Cover Art Handling

Album artwork retrieval occurs through _download_cover() in youtube_downloader.py lines 97-104, which delegates to ImageDownloader.get_image_from_url(). When image servers return 404 errors or connection timeouts, the method returns None rather than raising exceptions.

The MusicFileMetadata class accepts this None value gracefully, embedding audio metadata without cover art rather than failing the entire download.

Lyrics Service Unavailability

The _save_lyrics() method (lines 20-34 in youtube_downloader.py) interfaces with LrclibAPI to fetch synchronized lyrics. If the service returns instrumental tags, empty responses, or connection errors, the method returns False and updates the track object via track.with_lyrics_status(False).

The audio file persists despite lyrics unavailability, ensuring that network issues with secondary services never compromise the primary audio download.

Batch Download Resilience

Partial Success in Playlists and Albums

The download_playlist() method in youtube_downloader.py (lines 33-48) implements defensive validation before processing, checking for empty playlist names and zero-length track lists. During iteration (lines 48-64), each track download executes in an isolated try … except block.

The method maintains a failed_tracks collection while continuing processing, ultimately returning True if at least one track succeeded or False only for catastrophic failures (invalid metadata or total failure). This design ensures that a single unavailable track never aborts a 500-song playlist download.

Code Examples: Handling Failures in Practice

The following examples demonstrate how SpotifySaver's error handling works in practice when dealing with common failure scenarios when downloading from YouTube Music.

Handling Individual Track Failures

This example shows how to process a single track while handling potential search failures, download errors, and missing metadata:

from spotifysaver.downloader.youtube_downloader import YouTubeDownloader
from spotifysaver.models.track import Track

downloader = YouTubeDownloader(base_dir="MyMusic")

# Build a Track instance (normally obtained from Spotify API)

track = Track(
    name="Imagine",
    artists=["John Lennon"],
    album_name="Imagine",
    release_date="1971-09-09",
    number=1,
    cover_url=None,
)

# Attempt the download – the method already handles most failures internally

audio_path, updated_track = downloader.download_track(
    track,
    output_format=AudioFormat.MP3,
    bitrate=Bitrate.B192,
    download_lyrics=True,
)

if audio_path:
    print(f"✅ Download succeeded: {audio_path}")
else:
    print("❌ Download failed – see logs for details")

All failure scenarios—including no match found, yt-dlp errors, missing cover art, and lyric service failures—are logged internally; the caller only needs to check the returned tuple for None values to detect failures.

Processing Playlists with Partial Failures

This example demonstrates how SpotifySaver handles batch downloads where individual tracks may fail without stopping the entire operation:

from spotifysaver.downloader.youtube_downloader import YouTubeDownloader
from spotifysaver.models.playlist import Playlist

dl = YouTubeDownloader()
playlist = Playlist(
    name="My Favorite Hits",
    tracks=[track1, track2, track3],
    cover_url="https://i.scdn.co/image/abc123",
)

success = dl.download_playlist(
    playlist,
    output_format=AudioFormat.OPUS,
    bitrate=Bitrate.B256,
    download_lyrics=True,
    cover=True,
    nfo=False,
)

if success:
    print("✅ Playlist downloaded (some tracks may have been skipped)")
else:
    print("❌ Playlist download failed – possibly empty or invalid name")

The download_playlist method collects per-track failures in a failed_tracks list, logs detailed error information, and still returns True if at least one track succeeded, ensuring that transient failures for individual songs do not invalidate an entire batch operation.

Summary

SpotifySaver addresses common failure scenarios when downloading from YouTube Music through a comprehensive fail-soft architecture:

  • Search Resilience: The YoutubeMusicSearcher class implements multi-strategy matching with 3-attempt retry loops for API errors, returning None gracefully when tracks cannot be found rather than crashing.
  • Atomic Downloads: The download_track() method removes partial files using output_path.unlink() when yt-dlp fails, preventing corrupted audio from entering your library.
  • Graceful Degradation: Missing cover art and lyrics service failures return None or False status flags without aborting the primary audio download, ensuring secondary service issues don't compromise core functionality.
  • Batch Isolation: Playlist downloads isolate each track in separate exception handlers, collecting failures in failed_tracks while continuing processing, ensuring partial success for large batches.

Frequently Asked Questions

What happens when YouTube Music has no match for a specific track?

When YoutubeMusicSearcher.search_track() cannot locate a track through exact, album-context, or fuzzy matching strategies in spotifysaver/services/youtube_api.py lines 94-100, it logs an error and returns None. The downloader then returns (None, None), allowing the application to skip the missing track and continue with remaining downloads without crashing the batch process.

Does SpotifySaver automatically retry failed API calls?

Yes, the search_track() method in youtube_api.py lines 40-55 implements a default 3-attempt retry loop for transient failures. It catches YouTubeAPIError, AlbumNotFoundError, and InvalidResultError, logging warnings between attempts. Only after all retries exhaust does it return a final failure status, ensuring temporary network hiccups don't immediately abort operations.

Can a single failed track stop my entire playlist download?

No. The download_playlist() method in youtube_downloader.py lines 48-64 isolates each track download in separate try … except blocks. Failures are collected in a failed_tracks list while processing continues. The method returns True if at least one track succeeds, ensuring that a single unavailable track never aborts a 500-song playlist download.

How does SpotifySaver prevent corrupted audio files from remaining in my library?

The download_track() method in youtube_downloader.py lines 140-166 implements atomic download handling. When yt-dlp encounters HTTP errors, unavailable fragments, or other execution failures, the exception handler calls output_path.unlink() to delete partially-written files before returning (None, None). This ensures only complete, valid audio files persist in your destination directory.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →