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

> Learn about YouTube Music download errors and see how SpotifySaver's fail-soft architecture gracefully handles network, API, and metadata failures without corrupting your library.

- Repository: [Gabriel Baute/spotify-saver](https://github.com/gabrielbaute/spotify-saver)
- Tags: best-practices
- Published: 2026-03-02

---

**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

### Handling Unmatched Tracks in YouTube Music Search

The `YoutubeMusicSearcher.search_track()` method in [`spotifysaver/services/youtube_api.py`](https://github.com/gabrielbaute/spotify-saver/blob/main/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`](https://github.com/gabrielbaute/spotify-saver/blob/main/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`](https://github.com/gabrielbaute/spotify-saver/blob/main/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`](https://github.com/gabrielbaute/spotify-saver/blob/main/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`](https://github.com/gabrielbaute/spotify-saver/blob/main/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`](https://github.com/gabrielbaute/spotify-saver/blob/main/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`](https://github.com/gabrielbaute/spotify-saver/blob/main/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:

```python
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:

```python
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`](https://github.com/gabrielbaute/spotify-saver/blob/main/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`](https://github.com/gabrielbaute/spotify-saver/blob/main/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`](https://github.com/gabrielbaute/spotify-saver/blob/main/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`](https://github.com/gabrielbaute/spotify-saver/blob/main/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.