Skip to content

fix(billing): add panel fallback + robust matching to precondition modal routing (FE-878)#12854

Closed
MaanilVerma wants to merge 4 commits into
Comfy-Org:jaewon/fe-878-bug-subscription-required-error-message-feels-choppyabruptfrom
MaanilVerma:fix/fe-878-precondition-fallback-and-string-error
Closed

fix(billing): add panel fallback + robust matching to precondition modal routing (FE-878)#12854
MaanilVerma wants to merge 4 commits into
Comfy-Org:jaewon/fe-878-bug-subscription-required-error-message-feels-choppyabruptfrom
MaanilVerma:fix/fe-878-precondition-fallback-and-string-error

Conversation

@MaanilVerma

Copy link
Copy Markdown
Collaborator

Summary

Builds on top of #12785 precondition→modal routing: adds an error-panel fallback so a gated-off modal never leaves the user with a blank screen, plus more robust paywall matching.

Changes

  • What:
    • Panel fallback — canRoutePreconditionToModal gate (shared by the dialog opener, queue catch, and execution store) suppresses the error panel only when a modal can actually open; otherwise the error stays in the panel. Fixes the blank-screen case when the subscription modal no-ops (non-cloud or __CONFIG__.subscription_required off).
    • Match PAYMENT_REQUIRED by exception type, not just the message string, so classification survives backend wording changes.
    • Normalize string-shaped /prompt response errors (resolvePromptResponsePrecondition) so the queue paywall routes regardless of payload shape.
    • Refactor: single pure routing predicate removes the duplicated subscription-mode check and the executionStore → dialog → auth coupling.

Review Focus

  • The fallback rule: matched precondition + modal opens → panel suppressed; matched + modal can't open → panel kept (never blank); unmatched → panel as before.

  • canRoutePreconditionToModal is pure (reads isCloud + __CONFIG__, no auth/dialog imports) and is the single source of truth used by useAccountPreconditionDialog.open, the queue catch, and executionStore.

  • subscriptionPaywallError.spec.ts updated: in the OSS test build (non-cloud) the paywall correctly falls back to the panel.

  • Fixes Subscription paywall shows raw "Subscription required to queue workflows" with no upgrade action #12840

…type

The queue paywall arrives as exception type PAYMENT_REQUIRED; matching it by type
(not just the message string) keeps classification stable if the backend wording
changes.
… open

Precondition routing dropped subscription/sign-in/credit errors from the panel
and opened a modal, but the subscription modal no-ops when subscription mode is
disabled (non-cloud or config off), leaving the user with nothing on screen.

Add a pure canRoutePreconditionToModal gate (no auth/dialog coupling) shared by
the dialog opener, the queue catch, and the execution store: suppress the panel
only when a modal can actually take over, otherwise keep the error visible. Also
normalize string-shaped /prompt response errors so the queue paywall routes
regardless of payload shape.
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jun 15, 2026
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fadd69fe-a18d-4770-84c0-e98a96245484

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown

🎨 Storybook: loading Building...

@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown

🎭 Playwright: ✅ 1668 passed, 0 failed · 3 flaky

📊 Browser Reports
  • chromium: View Report (✅ 1647 / ❌ 0 / ⚠️ 3 / ⏭️ 5)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 18 / ❌ 0 / ⚠️ 0 / ⏭️ 0)

@dante01yoon dante01yoon left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed at 8632d1a. The panel-fallback design — gate modal routing on canRoutePreconditionToModal, keep the error in the panel when the modal can't open — is sound and applied consistently across all three surfaces (dialog opener, queue catch, execution store). canRoutePreconditionToModal is correctly pure, and the PAYMENT_REQUIRED-by-type rule sits after the credit rules in runtimeErrorMatcher, so it won't misroute insufficient-credits.

One blocking regression in the queue catch — details inline.

  • issue: (1, blocking) resolvePromptResponsePrecondition(error.response.error) throws a TypeError on a /prompt error body that has no top-level error key (e.g. the 403 middleware {"message":"..."} shape the same catch block handles a few lines below). The pre-refactor code guarded this with typeof error.response.error === 'object'; the refactor dropped that guard.

Note: typecheck / unit / Playwright checks had not reported at review time, and no test covers the undefined-error queue path, so this regression is currently uncaught by CI.

Comment thread src/scripts/app.ts
…or field

The /prompt body is unvalidated JSON, so error.response.error can be undefined
(e.g. the 403 middleware { message } shape) despite the typed union. Guard the
object branch in resolvePromptResponsePrecondition so it returns undefined
instead of throwing, letting the queue catch fall through to its 403 handler.
Add unit tests for the undefined and no-error-field cases.
@MaanilVerma MaanilVerma requested a review from dante01yoon June 15, 2026 14:51
@MaanilVerma MaanilVerma removed their assignment Jun 16, 2026
@dante01yoon dante01yoon added the needs-backport Fix/change that needs to be cherry-picked to the current feature freeze branch label Jun 16, 2026
@dante01yoon

Copy link
Copy Markdown
Collaborator

I recommend you merge this PR once parent got merged

@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 73.07692% with 7 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/scripts/app.ts 0.00% 7 Missing ⚠️
@@                                             Coverage Diff                                              @@
##           jaewon/fe-878-bug-subscription-required-error-message-feels-choppyabrupt   #12854      +/-   ##
============================================================================================================
- Coverage                                                                     62.14%   61.67%   -0.47%     
============================================================================================================
  Files                                                                          1458     1459       +1     
  Lines                                                                         75108    75337     +229     
  Branches                                                                      21167    19641    -1526     
============================================================================================================
- Hits                                                                          46675    46466     -209     
- Misses                                                                        28089    28517     +428     
- Partials                                                                        344      354      +10     
Flag Coverage Δ
unit 61.67% <73.07%> (-0.47%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...iption/composables/useAccountPreconditionDialog.ts 100.00% <100.00%> (ø)
...latform/errorCatalog/accountPreconditionRouting.ts 100.00% <100.00%> (ø)
src/platform/errorCatalog/runtimeErrorMatcher.ts 98.74% <100.00%> (+<0.01%) ⬆️
src/stores/executionStore.ts 89.72% <100.00%> (+0.03%) ⬆️
src/scripts/app.ts 23.46% <0.00%> (-0.49%) ⬇️

... and 98 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dante01yoon

Copy link
Copy Markdown
Collaborator

@MaanilVerma can you check CI failing

@MaanilVerma

MaanilVerma commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator Author

@MaanilVerma can you check CI failing

@dante01yoon Yes, I saw that! Those were random errors

Now all CI's have passed

@MaanilVerma MaanilVerma removed their assignment Jun 17, 2026
…eels-choppyabrupt' into fix/fe-878-precondition-fallback-and-string-error
@dante01yoon dante01yoon deleted the branch Comfy-Org:jaewon/fe-878-bug-subscription-required-error-message-feels-choppyabrupt June 19, 2026 01:19
@dante01yoon

Copy link
Copy Markdown
Collaborator

Closing as the changes were folded into the parent #12785 and merged to main, so this stacked PR is now redundant (#12840 closed by that merge too). Thanks @MaanilVerma!

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

Labels

needs-backport Fix/change that needs to be cherry-picked to the current feature freeze branch size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants