Fix: terminal Muapi errors are retried for 30 minutes instead of failing fast - #314
Open
alnavone wants to merge 1 commit into
Open
Fix: terminal Muapi errors are retried for 30 minutes instead of failing fast#314alnavone wants to merge 1 commit into
alnavone wants to merge 1 commit into
Conversation
pollForResult throws on a 4xx response and on an explicit "failed" job status, but both throws are inside the try block, so the loop's own catch swallows them and keeps polling. Video generation polls 900 times at 2s intervals, so an out-of-credits, rate-limited, or already-failed job is indistinguishable from one still running for the full 30 minutes -- the UI just shows a spinner. The `if (response.status >= 500) continue` guard shows the intent was to fail fast on 4xx; the control flow never did. Tag terminal errors with isFatal and rethrow them from the catch. 5xx and network errors stay retryable. Fixed in all three polling loops: - src/lib/muapi.js pollForResult (Electron renderer) - packages/studio/src/muapi.js pollForResult (web studio) - packages/studio/src/muapi.js pollWorkflowResult Adds tests/muapiPolling.test.js, which extracts the shipped pollForResult and asserts a 402 and a failed status each stop after exactly one request, while 503, pending, and network errors still retry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix: terminal Muapi errors are retried for 30 minutes instead of failing fast
A generation that has already failed server-side — out of credits, rate limited, bad request — is indistinguishable from one still running, for up to half an hour. The UI shows a spinner the whole time and never surfaces an error.
Found while debugging a video generation that appeared to hang for 15+ minutes. The job had actually been rejected with a
400almost immediately.The bug
pollForResultthrows on a fatal HTTP status and on an explicitfailedjob status. Both throws are inside thetryblock, so the loop's owncatchswallows them and keeps polling:The
if (response.status >= 500) continueguard shows the intent was to treat 5xx as transient and anything else as fatal. The control flow never did that.Impact scales with
maxAttempts:generateImagegenerateVideoA
402(out of credits),429(rate limited),401, or400gets retried 900 times. So does a job the server has explicitly reported asfailed.The fix
Tag terminal errors and rethrow them from the
catch:5xx responses and network errors stay retryable — those genuinely are transient.
Applied to all three polling loops, since the same pattern is duplicated:
src/lib/muapi.js—pollForResult(Electron renderer)packages/studio/src/muapi.js—pollForResult(web studio)packages/studio/src/muapi.js—pollWorkflowResultTests
tests/muapiPolling.test.js, matching the existingnode:testsuite. It extracts the realpollForResultfromsrc/lib/muapi.jsand runs it against a stubbedfetch, so it tests the shipped code rather than a copy of the logic. Extraction is brace-matched, not offset-based, so it survives edits to the surrounding file.402stops after exactly one requestfailedjob status stops after exactly one request503is retried, then succeedspendingkeeps polling until the job completes17 pre-existing tests still pass.
Note
This is independent of the Windows CUDA / sd.cpp packaging fixes I opened separately — different subsystem, different failure mode. The two branches touch no common files and can be reviewed and merged in either order.