Errors#

Every error tidalpy raises derives from TidalError, so one except clause catches the whole family. The most useful distinctions:

  • AuthError — log in (or refresh) and retry.

  • RateLimitError — transient; Tidal asked us to slow down (honours Retry-After, waits are bounded).

  • RegionLockedError — the catalogue exists but not in the account’s country.

  • PreviewOnlyError — only a 30-second preview is available for this rendition.

  • QualityUnavailableError — the requested quality is not licensed for this account/track.

  • CancelledError — the host cancelled the operation (download runs return a report; streams raise).

  • ConfigError — bad configuration; fix the config, retrying won’t help.

Structured exception hierarchy for tidalpy.

Every error carries a machine-readable to_dict() payload so hosts (Django models, Celery task rows, logs) can persist failures without parsing human-readable text. The legacy integration had to guess what happened from CLI exit codes and stderr fragments; this hierarchy makes the failure mode explicit and testable.

Error taxonomy#

exception tidalpy.errors.AuthError(message, *details, status_code=None, sub_status=None)[source]#

Bases: TidalError

Credentials are missing, expired, or unusable for this client.

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

code: str = 'auth'#
exception tidalpy.errors.CancelledError(message, *details, status_code=None, sub_status=None)[source]#

Bases: TidalError

The host cancelled the in-flight operation.

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

code: str = 'cancelled'#
exception tidalpy.errors.ConfigError(message, *details, status_code=None, sub_status=None)[source]#

Bases: TidalError

Configuration is missing or inconsistent.

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

code: str = 'config'#
exception tidalpy.errors.DiskFullError(message, *details, status_code=None, sub_status=None)[source]#

Bases: DownloadError

The destination disk ran out of space mid-download.

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

code: str = 'disk-full'#
retryable: bool = False#
exception tidalpy.errors.DownloadError(message, *details, status_code=None, sub_status=None)[source]#

Bases: TidalError

Fetching the media bytes failed (network, truncation, disk).

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

code: str = 'download'#
retryable: bool = True#
exception tidalpy.errors.ManifestError(message, *details, status_code=None, sub_status=None)[source]#

Bases: StreamError

A stream manifest is missing, corrupt, oversized, or DRM-protected.

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

code: str = 'manifest'#
exception tidalpy.errors.NotFoundError(message, *details, status_code=None, sub_status=None)[source]#

Bases: TidalError

The resource id does not exist (v1 and, when applicable, v2).

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

code: str = 'not-found'#
exception tidalpy.errors.PreviewOnlyError(message, *details, status_code=None, sub_status=None)[source]#

Bases: TidalError

Only a preview (e.g. free account) is offered for this content.

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

code: str = 'preview-only'#
exception tidalpy.errors.QualityUnavailableError(message, *details, status_code=None, sub_status=None)[source]#

Bases: TidalError

No stream could be resolved at any attempted quality tier.

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

code: str = 'quality-unavailable'#
exception tidalpy.errors.RateLimitError(message, *details, status_code=None, sub_status=None)[source]#

Bases: TidalError

TIDAL returned 429 repeatedly; the wait budget is exhausted.

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

code: str = 'rate-limited'#
retryable: bool = True#
exception tidalpy.errors.RegionLockedError(message, *details, status_code=None, sub_status=None)[source]#

Bases: TidalError

The content is not available in the account’s country.

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

code: str = 'region-locked'#
exception tidalpy.errors.StreamError(message, *details, status_code=None, sub_status=None)[source]#

Bases: TidalError

Playback info / stream resolution failed for other reasons.

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

code: str = 'stream'#
exception tidalpy.errors.TidalApiError(message, status_code=None, sub_status=None, codes=None, *details)[source]#

Bases: TidalError

A Tidal API rejection with HTTP/subStatus context attached.

Parameters:
  • message (str)

  • status_code (int | None)

  • sub_status (int | str | None)

  • codes (list[str] | None)

  • details (Any)

Return type:

None

__init__(message, status_code=None, sub_status=None, codes=None, *details)[source]#
Parameters:
Return type:

None

code: str = 'api'#
exception tidalpy.errors.TidalError(message, *details, status_code=None, sub_status=None)[source]#

Bases: Exception

Base class for every error raised by tidalpy.

Every error carries a stable machine code (e.g. "auth-expired") that hosts may key off without string-matching the message, and a retryable flag: True when the same call may succeed later without host action (transient network, rate limit), False for permanent failures (bad token, region lock) where retrying wastes time.

Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

__init__(message, *details, status_code=None, sub_status=None)[source]#
Parameters:
  • message (str)

  • details (Any)

  • status_code (int | None)

  • sub_status (int | str | None)

Return type:

None

to_dict()[source]#

JSON-serialisable representation (safe for Django JSONField).

Return type:

dict[str, Any]

code: str = 'tidal-error'#
retryable: bool = False#
status_code: int | None#
sub_status: int | str | None#
exception tidalpy.errors.UnsupportedType(message, *details, status_code=None, sub_status=None)[source]#

Bases: TidalError

The resource kind is not handled (e.g. videos) or not requested.

Parameters:
Return type:

None

code: str = 'unsupported-type'#