Skip to content

Reliability: license-exchange and webplayback POSTs are never retried - RetryTransport's default method list excludes POST #7

Description

@JavaGT

Audit finding (read-only review of gamdl 3.8.5, commit 478c3f2). Cross-checked by two models; both judge it real.

Lens: reliability
Suggested grade: Strong (grok: high; luna: medium)

Evidence

  • gamdl/api/apple_music.py:192-198 — the shared client's retry transport sets no allowed methods:
transport=RetryTransport(
    retry=Retry(
        total=6,
        backoff_factor=1,
        status_forcelist=[429, 500, 502, 503, 504],
    )
),
  • In httpx-retries 0.4.6 (the pinned version in uv.lock), the default retryable method set is HEAD, GET, PUT, DELETE, OPTIONS, TRACE — POST is excluded (verified against the library source, RETRYABLE_METHODS constant).
  • get_webplayback (apple_music.py:725) and get_license_exchange (apple_music.py:760) are client.post() calls on this client. So 429/5xx responses on the DRM license-exchange and webplayback endpoints are never retried, silently defeating status_forcelist=[429,...] on exactly the calls most likely to be throttled. A single transient 429 fails the track.
  • Related upstream pain: Error fetching license exchange data (Status code: 429) glomatico/gamdl#306 reports 429 license-exchange failures (mechanism matches; the specific user's root cause not confirmed).

Model verdicts

  • luna (gpt-5.6-luna): real, medium. "Adding POST to allowed_methods is reasonable if these operations are demonstrably safe to repeat... consider retrying only the specific POST endpoints rather than all POSTs globally."
  • grok (grok-4.6): real, high. "Retry those two POSTs only, not every POST on the shared client... Bodies must be rewindable (JSON/bytes is fine)... License exchange is on the critical path for protected tracks, so a single 429 becoming a hard fail is worse than waiting."

Fix direction: per-request or dedicated-client Retry(allowed_methods=[...,"POST"], ...) for get_webplayback and get_license_exchange only (both are idempotent read-style POSTs; JSON bodies are rewindable). Do not blanket-enable POST retries on the shared client.

Adopt as upstream contribution candidate? (adopt / adapt / reject)

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions