Skip to content

fix: stop HuggingFace rate-limit failures from breaking voice engine downloads (#683)#704

Open
shreeraman96 wants to merge 1 commit into
mainfrom
fix/683-rate-limit-download
Open

fix: stop HuggingFace rate-limit failures from breaking voice engine downloads (#683)#704
shreeraman96 wants to merge 1 commit into
mainfrom
fix/683-rate-limit-download

Conversation

@shreeraman96

@shreeraman96 shreeraman96 commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Description

  • Skip the cache-clear + re-prepare recovery in ASRService.prepareProviderWithRecovery when the first prepare attempt failed due to HuggingFace rate limiting (rateLimited, htmlErrorResponse) or a network error, rethrowing instead so cached model files stay resumable.
  • New classifier walks the NSUnderlyingErrorKey chain (depth-capped) so errors reboxed by provider layers are still recognized; cancellation is excluded and keeps its existing handling.

Why: clearing the provider cache on a transient 429 forces a full re-download, which burns more of HuggingFace's fixed 500-requests/5-minutes per-IP API window and turns one rate limit into a self-reinforcing failure loop where every engine's download fails ("Rate limited while listing files"). Root fix lands in FluidAudio (altic-dev/FluidAudio#2 — single recursive listing, header-aware retries, no cache wipe on rate limits); this PR removes the app-level amplifier. The app picks up the FluidAudio fix automatically once #2 merges into the pinned B/cohere-coreml-asr branch.

Repro evidence (offline stub HuggingFace server, real Parakeet v3 tree): before the fixes, one download gesture cost 41 listing API calls, any 429 failed instantly with the exact issue error, and a mid-flight failure wiped the cache and re-listed (a 45-call budget that fit one full pass still blew up at call #46). After the fixes: 1 listing call, downloaded file set byte-identical (23/23), sustained 429s produce header-paced retries then a clean error with the cache intact, and corrupt-model recovery still works. Full tables in altic-dev/FluidAudio#2.

Type of Change

  • 🐞 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 🧹 Chore
  • 📝 Documentation update

Related Issue or Discussion

Closes #683

Testing

  • Tested on Intel Mac
  • Tested on Apple Silicon Mac
  • Tested on macOS version: 26.5.1
  • Ran linter locally: swiftlint --strict --config .swiftlint.yml Sources (0 violations on the changed file)
  • Ran formatter locally: swiftformat --config .swiftformat Sources (changed file already fails formatter lint on main; not reformatting ~3k unrelated lines in this PR)
  • Ran tests locally: FluidAudio DownloadUtilsRateLimitTests 15/15 pass; app built via ./build.sh unsigned; behavior verified end-to-end with an offline stub HuggingFace server (details in fix: eliminate HuggingFace rate-limit failures in model downloads FluidAudio#2)

Screenshots / Video

  • No UI/visual changes; screenshots/video are not applicable.

Notes

Companion root-cause PR: altic-dev/FluidAudio#2. This change is safe standalone (it only narrows a destructive retry), but the user-facing rate-limit failures in #683 fully disappear when both land.

The same dependency bump also fixes #679 (progress stuck at 3%, then completes all at once). Root cause, verified empirically: the FluidAudio revision pinned by v1.6.5 (edee7154) attaches a progress delegate but downloads via the async session.download(for:) convenience, which never delivers didWriteData — so progress only ticks at file boundaries and freezes for the entire multi-hundred-MB encoder transfer. FluidAudio 6af7925 (merged to B/cohere-coreml-asr two days after the 1.6.5 pin) rewrites this with a delegate-backed download task. Measured with an offline stub (30 MB file): pinned revision = 23 progress events / 9 distinct values for a whole repo download; current branch incl. FluidAudio#2 = 1,142 events / 73 distinct values (continuous). Re-pinning FluidAudio to the branch head once FluidAudio#2 merges resolves both #683 and #679.

Clearing the provider cache and re-preparing on a transient 429 or
network failure forces a full re-download, which burns more of
HuggingFace's fixed per-IP API window and turns one rate limit into a
self-reinforcing failure loop. Classify rate-limit/HTML/network errors
(walking the underlying-error chain) and rethrow them instead, leaving
cached files resumable.
@greptile-apps

greptile-apps Bot commented Jul 24, 2026

Copy link
Copy Markdown

Greptile Summary

Prevents transient Hugging Face rate-limit and network errors from triggering destructive cache clearing by classifying wrapped download errors and rethrowing them so partial model downloads remain resumable.

Confidence Score: 5/5

The PR appears safe to merge with no actionable defects identified in the changed recovery behavior.

The new branch preserves cached model files for recognized rate-limit and transport failures while retaining the existing cancellation handling and corruption-recovery path for other preparation errors.

Reviews (1): Last reviewed commit: "fix: skip cache-clear recovery on rate-l..." | Re-trigger Greptile

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 63fac7d836

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +3247 to +3249
if let hfError = candidate as? DownloadUtils.HuggingFaceDownloadError {
switch hfError {
case .rateLimited, .htmlErrorResponse:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Guard FluidAudio-only error handling on Intel builds

In the Intel build path, ASRService.swift does not import FluidAudio because the import at the top is behind #if arch(arm64), and the repo provides Intel stubs for FluidAudio-backed providers so Whisper/Apple Speech can still build. This new unconditional reference to DownloadUtils.HuggingFaceDownloadError therefore leaves DownloadUtils out of scope for x86_64 macOS builds, breaking the Intel support path; wrap this branch in the same architecture/import guard or avoid the FluidAudio type outside arm64 code.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Installation of Parakeet (and other voice engines) failing on Mac [BUG] cant download Voice Model.

1 participant