Skip to content

fix: surface bridge deposit errors instead of failing silently#2329

Open
kushagrasarathe wants to merge 2 commits into
devfrom
fix/surface-onramp-errors
Open

fix: surface bridge deposit errors instead of failing silently#2329
kushagrasarathe wants to merge 2 commits into
devfrom
fix/surface-onramp-errors

Conversation

@kushagrasarathe

Copy link
Copy Markdown
Contributor

Summary

EEA-uplift users whose Bridge KYC docs are under review were creating deposits that failed with zero feedback — they retried blind (user recording confirmed; ~369 prod users currently sit in the waiting-on-provider state). Three silent-failure holes on the bank deposit path:

  1. useCreateOnramp threw a hardcoded generic message without parsing the backend's { error } body (the comment claimed it parsed; it didn't). Backend reasons like "Could not create transfer: customer is under review" were discarded.
  2. The page's catch gated the visible error on the hook's error state, which hasn't flushed when the synchronous catch runs — always null on first attempt, so nothing displayed.
  3. gate.kind === 'waiting-on-provider' silently no-op'd the Continue button — no "under review" UX existed anywhere.

Fix: parse the error body (error/message keys, generic fallback), show the caught message directly in the catch, and show a friendly "your verification details are being reviewed" message on the waiting-on-provider gate.

Risks / breaking changes

  • FE-only; no backend or contract changes.
  • Backend error strings are now shown verbatim to users — they're already user-appropriate on this route ("Bridge Terms of Service must be accepted…", "Additional KYC may be required"), and any string beats the silent failure.
  • Blast radius: bank deposit page + one hook (single consumer).

QA

  • npm test — 107 suites green, incl. new useCreateOnramp hook tests + 2 page tests (error surfacing with unflushed hook state; waiting-on-provider message instead of dead button).
  • The strengthened page test reproduces the incident: old code fails it (hook error: null → no setError call), new code passes.
  • Manual repro path: sandbox user with Bridge rail in REQUIRES_EXTRA_INFORMATION + kyc_approval wait signal → deposit → Continue now shows the under-review message.

EEA-uplift users whose docs are under Bridge review were retrying deposits
with zero feedback: the onramp hook threw a hardcoded message without
reading the backend's { error } body, the page's catch read the hook's
error state before it flushed (always null on first attempt), and the
waiting-on-provider gate dead-ended the Continue button with no message.

Parse the error body, show the caught message directly, and tell
under-review users their verification is being processed.
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
peanut-wallet Ready Ready Preview, Comment Jul 2, 2026 12:00pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f09afa41-2703-4a24-ac50-0b42b9677657

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

Warning

Walkthrough skipped

File diffs could not be summarized.


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

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 5860.66 → 5861.65 (+0.99)
Findings: 0 net (+12 new, -12 resolved)

🆕 New findings (12)

  • critical complexity — src/app/(mobile-ui)/add-money/[country]/bank/page.tsx — CC 94, MI 57.68, SLOC 343
  • high hotspot — src/app/(mobile-ui)/add-money/[country]/bank/page.tsx — 51 commits, +562/-445 lines since 6 months ago
  • medium react-long-component — src/app/(mobile-ui)/add-money/[country]/bank/page.tsx:49 — OnrampBankPage is 466 lines — split it
  • medium high-mdd — src/app/(mobile-ui)/add-money/[country]/bank/page.tsx:49 — OnrampBankPage: MDD 142.6 (uses across many lines from declarations)
  • medium method-complexity — src/app/(mobile-ui)/add-money/[country]/bank/page.tsx:49 — OnrampBankPage CC 29 SLOC 164
  • medium complexity — src/hooks/useCreateOnramp.ts — CC 11, MI 57.84, SLOC 49
  • medium react-effect-derives-state — src/app/(mobile-ui)/add-money/[country]/bank/page.tsx:351 — small useEffect that only sets state from deps
  • low structural-dup — app/(mobile-ui)/add-money/[country]/bank/page.tsx:469 — 16 duplicate lines / 91 tokens with components/Claim/Link/views/BankFlowManager.view.tsx:610
  • low structural-dup — app/(mobile-ui)/add-money/[country]/bank/page.tsx:482 — 13 duplicate lines / 58 tokens with app/(mobile-ui)/withdraw/[country]/bank/page.tsx:557
  • low structural-dup — app/(mobile-ui)/add-money/[country]/bank/page.tsx:469 — 11 duplicate lines / 69 tokens with app/(mobile-ui)/withdraw/[country]/bank/page.tsx:544
  • low high-mdd — src/hooks/useCreateOnramp.ts:39 — useCreateOnramp: MDD 11.3 (uses across many lines from declarations)
  • low structural-dup — app/(mobile-ui)/add-money/[country]/bank/page.tsx:485 — 9 duplicate lines / 51 tokens with components/Claim/Link/views/BankFlowManager.view.tsx:628

✅ Resolved (12)

  • src/app/(mobile-ui)/add-money/[country]/bank/page.tsx — CC 94, MI 57.82, SLOC 339
  • src/app/(mobile-ui)/add-money/[country]/bank/page.tsx — 49 commits, +526/-423 lines since 6 months ago
  • src/app/(mobile-ui)/add-money/[country]/bank/page.tsx:49 — OnrampBankPage is 452 lines — split it
  • src/app/(mobile-ui)/add-money/[country]/bank/page.tsx:49 — OnrampBankPage: MDD 139.3 (uses across many lines from declarations)
  • src/app/(mobile-ui)/add-money/[country]/bank/page.tsx:49 — OnrampBankPage CC 29 SLOC 165
  • src/hooks/useCreateOnramp.ts — CC 6, MI 58.39, SLOC 51
  • src/app/(mobile-ui)/add-money/[country]/bank/page.tsx:337 — small useEffect that only sets state from deps
  • app/(mobile-ui)/add-money/[country]/bank/page.tsx:455 — 16 duplicate lines / 91 tokens with components/Claim/Link/views/BankFlowManager.view.tsx:610
  • app/(mobile-ui)/add-money/[country]/bank/page.tsx:468 — 13 duplicate lines / 58 tokens with app/(mobile-ui)/withdraw/[country]/bank/page.tsx:557
  • app/(mobile-ui)/add-money/[country]/bank/page.tsx:455 — 11 duplicate lines / 69 tokens with app/(mobile-ui)/withdraw/[country]/bank/page.tsx:544
  • src/hooks/useCreateOnramp.ts:32 — useCreateOnramp: MDD 10.0 (uses across many lines from declarations)
  • app/(mobile-ui)/add-money/[country]/bank/page.tsx:471 — 9 duplicate lines / 51 tokens with components/Claim/Link/views/BankFlowManager.view.tsx:628

📈 Painscore deltas (top movers)

File Before After Δ
src/hooks/useCreateOnramp.ts 8.4 9.0 +0.7

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 1648 ran, 0 failed, 0 skipped, 26.0s

📊 Coverage (unit)

metric %
statements 54.7%
branches 37.5%
functions 42.5%
lines 54.6%
⏱ 10 slowest test cases
time test
3.8s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
0.5s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.3s src/app/actions/__tests__/api-headers.test.ts › should include Content-Type in updateUserById
0.3s src/app/actions/__tests__/api-headers-extended.test.ts › should not include apiKey in updateUserById body
0.2s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid 9-digit US account
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle too long for US account
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid ETH address with surrounding spaces
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid US account with spaces
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle invalid ETH address (missing 0x prefix)
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid ENS name
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

Addresses code-review findings on the silent-failure fix:
- only surface the backend body for 4xx (client errors); 5xx bodies carry
  raw internal messages the global handler doesn't sanitize, so those fall
  back to the generic string (no internal-detail leak).
- make useCreateOnramp throw-only: its React error state had no reader after
  the page stopped destructuring it, and was the same stale-closure trap the
  page fix works around. The thrown Error carries the reason.
- reuse gate.userMessage for the waiting-on-provider copy instead of
  hardcoding, matching every other gate consumer.
- extract GENERIC_ONRAMP_ERROR so the fallback copy lives in one place.
- keep the distinct 'Unknown error' analytics label for non-Error throws.
@kushagrasarathe

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

1 participant