Skip to content

fix(billing): route subscription/sign-in/credit preconditions to modal, out of error panel (FE-878)#12785

Merged
dante01yoon merged 4 commits into
mainfrom
jaewon/fe-878-bug-subscription-required-error-message-feels-choppyabrupt
Jun 19, 2026
Merged

fix(billing): route subscription/sign-in/credit preconditions to modal, out of error panel (FE-878)#12785
dante01yoon merged 4 commits into
mainfrom
jaewon/fe-878-bug-subscription-required-error-message-feels-choppyabrupt

Conversation

@dante01yoon

@dante01yoon dante01yoon commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Account preconditions (sign-in / subscription / credits) on running a workflow now open their modal directly and stay out of the error panel + error count — previously subscription_required fell through to a red "1 ERROR — Subscription required to queue workflows" banner. This covers both paths: the execution_error websocket event and the POST /prompt 402 queue paywall ({ type: "PAYMENT_REQUIRED", message: "Subscription required to queue workflows" }), which is the exact payload reported in #12840.

Changes

  • What: execution_error is classified by a pure accountPreconditionRouting resolver (precedence sign-in > subscription > credits) and routed to the existing modal via useAccountPreconditionDialog; executionStore returns early for preconditions so they never populate lastExecutionError / lastPromptError / lastNodeErrors → fully excluded from the panel and totalErrorCount. Runtime credit error at a node → credits modal (out of panel; can name the node).
  • Queue paywall: the queuePrompt catch resolves the same precondition from the POST /prompt 402 response and opens the modal, short-circuiting before lastPromptError, so the queue paywall stays out of the panel too. The runtime matcher learns the "Subscription required to queue workflows" message.
  • Breaking: none.

Before / After

Free-tier queue paywall (POST /prompt → 402) on a cloud build:

Before — raw Subscription required to queue workflows surfaced in the error panel (no actionable upgrade):

before-error-panel

After — clean subscription modal opens; nothing in the error panel or error count:

after-subscription-modal

Review Focus

  • Routing-only — the run button is intentionally untouched. The original AC#3 ("no Subscribe-to-Run button") is superseded by the FE-978 run-lock decision (pre-emptive role-aware lock, Figma 3253-18671). Complements feat(billing): role-aware run-lock for cancelled/inactive team plans (FE-978) #12786 (FE-978 run-lock); disjoint file sets.
  • Tests: accountPreconditionRouting / useAccountPreconditionDialog / executionStore — each precondition routes to its modal and is excluded from the panel/count; precedence resolves on co-occurrence. Plus Playwright browser_tests/tests/subscriptionPaywallError.spec.ts — the queue paywall (402) stays out of the error panel, with a control asserting ordinary queue errors still surface. typecheck / oxlint / eslint / stylelint / oxfmt / knip clean.

Fixes FE-878
Fixes #12840

@dante01yoon dante01yoon requested a review from a team June 11, 2026 08:14
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jun 11, 2026
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a centralized account precondition handling system that classifies runtime errors (sign-in, subscription, credits) and routes them to dedicated modals. It replaces inline error-matching logic with a structured classification model and integrates precondition detection throughout the execution flow and application-level error handlers. The paywall error is now subscription-ally handled! 🎭

Changes

Account Precondition Error System

Layer / File(s) Summary
Precondition classification and routing model
src/platform/errorCatalog/accountPreconditionRouting.ts, src/platform/errorCatalog/accountPreconditionRouting.test.ts
Defines AccountPrecondition union type (sign_in, subscription, credits), maps catalog IDs to preconditions, and exports utilities: resolveAccountPrecondition() derives preconditions from RuntimeErrorInfo payloads, preconditionForCatalogId() and isAccountPreconditionCatalogId() check precondition mappings. Tests verify classification of exception types/messages, catalog ID lookup, and precedence.
Precondition dialog composable
src/platform/cloud/subscription/composables/useAccountPreconditionDialog.ts, src/platform/cloud/subscription/composables/useAccountPreconditionDialog.test.ts
Exports useAccountPreconditionDialog() hook with AccountPreconditionContext interface for optional node type. Routes each precondition to the correct modal: sign_in opens API nodes sign-in dialog, subscription opens subscription-required dialog, credits opens top-up credits dialog. Tests verify correct dialog invocation and argument shapes.
Execution store precondition handling
src/stores/executionStore.ts, src/stores/executionStore.test.ts
Integrates precondition detection into handleExecutionError() via new handleAccountPreconditionError() helper that uses resolveAccountPrecondition() to detect account-related errors. When detected, clears initialization state and resets execution for the affected prompt ID, then returns early to skip standard error-panel routing. Tests confirm precondition errors do not contribute to error panel or total error count, while normal runtime errors are still routed normally.
App-level execution error integration
src/scripts/app.ts, src/platform/errorCatalog/runtimeErrorMatcher.ts
Updates execution_error and queuePrompt error handlers to resolve account preconditions from exception type/message and open the precondition dialog when present, replacing prior inline string-matching for unauthorized and credits errors. Extends SUBSCRIPTION_REQUIRED_MESSAGES to classify both user and workspace subscription states, and exports RuntimeErrorInfo interface for public use.
Browser test coverage for subscription paywall
browser_tests/tests/subscriptionPaywallError.spec.ts
Adds Playwright UI regression tests verifying that subscription paywall errors (402 PAYMENT_REQUIRED) on queue execution do not display the error overlay in the error panel, while ordinary queue errors still show the overlay.

Suggested reviewers

  • jtydhr88
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed PR successfully implements account precondition routing to dedicated modals, addressing all requirements from #12840: subscription errors now trigger pricing modal instead of error panel.
Out of Scope Changes check ✅ Passed All changes directly support precondition routing for sign-in, subscription, and credits. No unrelated or extraneous modifications detected beyond stated objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jaewon/fe-878-bug-subscription-required-error-message-feels-choppyabrupt
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch jaewon/fe-878-bug-subscription-required-error-message-feels-choppyabrupt

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 11, 2026

Copy link
Copy Markdown

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 06/17/2026, 02:27:57 AM UTC

Links

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown

🎭 Playwright: ✅ 1680 passed, 0 failed · 1 flaky

📊 Browser Reports
  • chromium: View Report (✅ 1659 / ❌ 0 / ⚠️ 1 / ⏭️ 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)

@codecov

codecov Bot commented Jun 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.69767% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/scripts/app.ts 55.55% 4 Missing ⚠️
@@             Coverage Diff             @@
##             main   #12785       +/-   ##
===========================================
- Coverage   75.50%   62.14%   -13.37%     
===========================================
  Files        1568     1458      -110     
  Lines       96293    75108    -21185     
  Branches    27647    21167     -6480     
===========================================
- Hits        72710    46675    -26035     
- Misses      22808    28089     +5281     
+ Partials      775      344      -431     
Flag Coverage Δ
e2e ?
unit 62.14% <90.69%> (+0.48%) ⬆️

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.73% <ø> (+3.81%) ⬆️
src/stores/executionStore.ts 89.69% <100.00%> (-2.11%) ⬇️
src/scripts/app.ts 23.95% <55.55%> (-54.68%) ⬇️

... and 1154 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.

…(FE-878)

The free-tier queue paywall arrives on the POST /prompt path as { type: PAYMENT_REQUIRED, message: "Subscription required to queue workflows" }, which the execution_error-only routing did not cover, so it still surfaced as a raw error in the panel. Teach the runtime matcher this message and short-circuit the queuePrompt catch to open the precondition modal, keeping it out of the error panel and error count. Add an e2e regression test for the queue paywall plus a control for ordinary queue errors.

Fixes #12840

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
browser_tests/tests/subscriptionPaywallError.spec.ts (1)

46-49: ⚡ Quick win

Assert the paywall modal is shown, not only that the overlay is hidden.

This assertion is currently negative-only. If both overlay and precondition modal fail to appear, the test still passes. Add a positive assertion for the subscription dialog to lock the routing contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@browser_tests/tests/subscriptionPaywallError.spec.ts` around lines 46 - 49,
The current test assertion in the subscriptionPaywallError.spec.ts file only
verifies that the error overlay is hidden (a negative assertion), which means
the test passes even if the subscription paywall modal fails to appear. Add a
positive assertion that explicitly checks the subscription dialog or paywall
modal is visible/shown (using toBeVisible() or similar) alongside the existing
toBeHidden() assertion for the error overlay to ensure both conditions are
properly tested and lock the routing contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/scripts/app.ts`:
- Around line 1675-1685: The precondition routing logic in the code checks if
error.response.error is an object to determine preconditionResponseError, but
this field can also be a string value. Modify the condition that sets
preconditionResponseError to handle both cases: when error.response.error is an
object (extract type and message properties as currently done) and when it is a
string (treat the string itself as the exception message or type appropriately).
This ensures that both object-shaped and string-shaped prompt execution errors
are properly routed through the resolveAccountPrecondition function instead of
falling through to generic error handling.

---

Nitpick comments:
In `@browser_tests/tests/subscriptionPaywallError.spec.ts`:
- Around line 46-49: The current test assertion in the
subscriptionPaywallError.spec.ts file only verifies that the error overlay is
hidden (a negative assertion), which means the test passes even if the
subscription paywall modal fails to appear. Add a positive assertion that
explicitly checks the subscription dialog or paywall modal is visible/shown
(using toBeVisible() or similar) alongside the existing toBeHidden() assertion
for the error overlay to ensure both conditions are properly tested and lock the
routing contract.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d32d8418-dc53-4a8d-9a38-67a4999fd954

📥 Commits

Reviewing files that changed from the base of the PR and between 4d414ca and dc6c48c.

📒 Files selected for processing (4)
  • browser_tests/tests/subscriptionPaywallError.spec.ts
  • src/platform/errorCatalog/accountPreconditionRouting.test.ts
  • src/platform/errorCatalog/runtimeErrorMatcher.ts
  • src/scripts/app.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/platform/errorCatalog/accountPreconditionRouting.test.ts

Comment thread src/scripts/app.ts
@dante01yoon dante01yoon added needs-backport Fix/change that needs to be cherry-picked to the current feature freeze branch core/1.46 Backport PRs for core 1.46 cloud/1.46 Backport PRs for cloud 1.46 labels Jun 15, 2026
AustinMroz
AustinMroz previously approved these changes Jun 16, 2026
Comment thread src/platform/errorCatalog/accountPreconditionRouting.ts Outdated
Comment thread src/platform/errorCatalog/accountPreconditionRouting.ts Outdated
@AustinMroz AustinMroz assigned dante01yoon and unassigned AustinMroz Jun 16, 2026
@dante01yoon dante01yoon added the cloud/1.45 Backport PRs for cloud 1.45 label Jun 17, 2026
@coderabbitai coderabbitai Bot requested a review from jtydhr88 June 17, 2026 02:31

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/platform/errorCatalog/accountPreconditionRouting.test.ts (1)

17-84: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add an overlap-case test so precedence doesn’t play hide-and-seek.

The suite validates individual classifications, but it does not assert the
documented sign-in > subscription > credits precedence for payloads that could
match multiple precondition patterns. That’s a small gap with a big safety
rhyme: one extra test now avoids future “why did this route?” time.

Proposed test addition
 describe('resolveAccountPrecondition', () => {
+  it('prefers sign-in when sign-in and credits patterns both appear', () => {
+    expect(
+      resolveAccountPrecondition({
+        exceptionType: 'RuntimeError',
+        exceptionMessage:
+          'Unauthorized: Please login first to use this node. Payment Required: Please add credits to your account to use this node.'
+      })
+    ).toBe('sign_in')
+  })
+
   it('classifies a sign-in error', () => {

As per coding guidelines, "Write tests for all changes, especially bug fixes to catch future regressions."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/platform/errorCatalog/accountPreconditionRouting.test.ts` around lines 17
- 84, Add a new test case in the describe block for resolveAccountPrecondition
that validates the documented sign-in > subscription > credits precedence by
creating a payload that matches multiple precondition patterns and asserting
that the highest-precedence classification is returned. For example, craft an
exception that contains keywords matching both sign-in and subscription
patterns, and verify the function returns the sign-in classification rather than
subscription, ensuring the precedence rules are correctly enforced in the
resolveAccountPrecondition implementation.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/platform/errorCatalog/accountPreconditionRouting.test.ts`:
- Around line 17-84: Add a new test case in the describe block for
resolveAccountPrecondition that validates the documented sign-in > subscription
> credits precedence by creating a payload that matches multiple precondition
patterns and asserting that the highest-precedence classification is returned.
For example, craft an exception that contains keywords matching both sign-in and
subscription patterns, and verify the function returns the sign-in
classification rather than subscription, ensuring the precedence rules are
correctly enforced in the resolveAccountPrecondition implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b9d5f53b-8d01-4960-aa57-872bc6c99b48

📥 Commits

Reviewing files that changed from the base of the PR and between f8993d2 and 75131c2.

📒 Files selected for processing (3)
  • src/platform/errorCatalog/accountPreconditionRouting.test.ts
  • src/platform/errorCatalog/accountPreconditionRouting.ts
  • src/platform/errorCatalog/runtimeErrorMatcher.ts

mathtone pushed a commit to sketchyplans/ComfyUI-frontend-fork1 that referenced this pull request Jun 17, 2026
…(FE-978) (Comfy-Org#12786)

## Summary

Cancelled / inactive team plans keep members but lock runs; the run
button and the subscription-required dialog are now role-aware — owners
are routed to the pricing/subscribe flow, members (who cannot subscribe)
see "contact your workspace owner to resubscribe".

## Changes

- **What**: `SubscribeToRun.vue` becomes a role-aware locked run button
(owner → "Subscribe to Run"; member → neutral locked "Run" +
contact-owner tooltip; both open the subscription dialog).
`SubscriptionRequiredDialogContentWorkspace.vue` branches on role
(member → read-only contact-owner panel, no pricing/subscribe
affordance; owner → existing pricing/preview; member view suppressed for
`out_of_credits` so the active-but-low-credits path is unchanged).
`subscription.inactive.*` i18n keys.
- **Breaking**: none.

## Review Focus

- Role source =
`useWorkspaceUI().permissions.value.canManageSubscription` (owner /
personal = true, member = false) — the same accessor
`SubscriptionPanelContentWorkspace.vue` uses.
- **No BE work**: the run-gate already exists server-side
(`InactiveSubscriptionError`; `is_active` checked before funds). The
lock is gated on `is_active`, the same field the orchestrator uses, so
FE/BE stay consistent; leftover-credits-while-inactive remains blocked
by design.
- Complements Comfy-Org#12785 (FE-878 precondition→modal routing); disjoint file
sets. Design: DES-197, Figma 3253-18670 / 3253-18671 / 3246-13962.
- Tests: `SubscribeToRun` (4) / `CloudRunButtonWrapper` (3) /
`SubscriptionRequiredDialogContentWorkspace` role cases — member sees
contact-owner (no subscribe), owner sees pricing, run locks on
`!is_active` and unlocks when active (22 total); full `test:unit` green.

Fixes FE-978
@dante01yoon dante01yoon removed their assignment Jun 17, 2026
@dante01yoon dante01yoon added this pull request to the merge queue Jun 19, 2026
Merged via the queue into main with commit 67b884d Jun 19, 2026
49 checks passed
@dante01yoon dante01yoon deleted the jaewon/fe-878-bug-subscription-required-error-message-feels-choppyabrupt branch June 19, 2026 01:19
@github-actions

Copy link
Copy Markdown

⚠️ Backport to cloud/1.45 failed

Reason: Merge conflicts detected during cherry-pick of 67b884d

📄 Conflicting files
src/platform/errorCatalog/runtimeErrorMatcher.ts
🤖 Prompt for AI Agents
Backport PR #12785 (https://github.com/Comfy-Org/ComfyUI_frontend/pull/12785) to cloud/1.45.
Cherry-pick merge commit 67b884d0f747da5b53ad2e0432b8d6600bb6c329 onto new branch
backport-12785-to-cloud-1.45 from origin/cloud/1.45.
Resolve conflicts in: src/platform/errorCatalog/runtimeErrorMatcher.ts .
For test snapshots (browser_tests/**/*-snapshots/), accept PR version if
changed in original PR, else keep target. For package.json versions, keep
target branch. For pnpm-lock.yaml, regenerate with pnpm install.
Ask user for non-obvious conflicts.
Create PR titled "[backport cloud/1.45] <original title>" with label "backport".
See .github/workflows/pr-backport.yaml for workflow details.

cc @dante01yoon

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

Labels

cloud/1.45 Backport PRs for cloud 1.45 cloud/1.46 Backport PRs for cloud 1.46 needs-backport Fix/change that needs to be cherry-picked to the current feature freeze branch size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Subscription paywall shows raw "Subscription required to queue workflows" with no upgrade action

3 participants