fix(manteca): handle TAX_ID_MISMATCH error code for Brazil CPF#1619
fix(manteca): handle TAX_ID_MISMATCH error code for Brazil CPF#1619Hugo0 merged 1 commit intopeanut-walletfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughExtended Manteca withdraw error handling to treat Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review in depth. |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/app/(mobile-ui)/withdraw/manteca/page.tsx (1)
242-257: Consider hardening mismatch messaging + de-duplicating error-code literals.The new
TAX_ID_MISMATCH || CUIT_MISMATCHhandling matches the PR intent and the more generic fallback copy looks right (and aligns with the “prefer generic error messages for hotfixes” learning). Based on learnings, …Two small improvements to consider:
- If
result.messagecan be a technical/backend string, you may want to always show the UI-owned copy for these mismatch codes (to keep it consistently user-friendly and language-consistent).- Extract the mismatch codes into a constant/set to reduce string-literal drift.
Proposed tweak
+const TAX_ID_MISMATCH_ERRORS = new Set(['TAX_ID_MISMATCH', 'CUIT_MISMATCH'] as const) if (result.error) { // Handle specific error types with user-friendly messages // TAX_ID_MISMATCH covers both Argentina (CUIT) and Brazil (CPF) - if (result.error === 'TAX_ID_MISMATCH' || result.error === 'CUIT_MISMATCH') { + if (TAX_ID_MISMATCH_ERRORS.has(result.error as any)) { setErrorMessage( - result.message ?? - 'The bank account you entered is not registered under your name. You can only withdraw to accounts linked to your identity. Please contact support to request a refund.' + 'The bank account you entered is not registered under your name. You can only withdraw to accounts linked to your identity. Please contact support to request a refund.' ) setStep('failure') } else if (result.error === 'Unexpected error') {
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/app/(mobile-ui)/withdraw/manteca/page.tsx
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1094
File: src/components/AddWithdraw/DynamicBankAccountForm.tsx:279-279
Timestamp: 2025-08-14T08:02:26.705Z
Learning: For hotfixes in the peanut-ui codebase, prefer generic error messages over specific validation error details until the copy can be reviewed with the team, even when the validation functions return detailed error messages.
Learnt from: Hugo0
Repo: peanutprotocol/peanut-ui PR: 942
File: src/components/AddMoney/consts/index.ts:2151-2162
Timestamp: 2025-06-30T10:44:08.048Z
Learning: Hugo0 often agrees with refactoring suggestions but defers implementation due to time constraints, preferring to track improvements as follow-up issues when they're part of larger architectural changes.
📚 Learning: 2025-05-22T15:38:48.586Z
Learnt from: kushagrasarathe
Repo: peanutprotocol/peanut-ui PR: 869
File: src/app/(mobile-ui)/withdraw/page.tsx:82-88
Timestamp: 2025-05-22T15:38:48.586Z
Learning: The country-specific withdrawal route exists at src/app/(mobile-ui)/withdraw/[...country]/page.tsx and renders the AddWithdrawCountriesList component with flow="withdraw".
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2025-09-18T09:30:42.901Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1230
File: src/app/(mobile-ui)/withdraw/page.tsx:92-97
Timestamp: 2025-09-18T09:30:42.901Z
Learning: In src/app/(mobile-ui)/withdraw/page.tsx, the useEffect that calls setShowAllWithdrawMethods(true) when amountFromContext exists is intentionally designed to run only on component mount (empty dependency array), not when amountFromContext changes. This is the correct behavior for the withdraw flow where showing all methods should only happen on initial load when an amount is already present.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2024-11-18T21:36:11.486Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 535
File: src/components/Claim/Claim.tsx:142-146
Timestamp: 2024-11-18T21:36:11.486Z
Learning: In `src/components/Claim/Claim.tsx`, external calls like token price fetching and cross-chain details retrieval are already encapsulated within existing `try...catch` blocks, so additional error handling may be unnecessary.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2025-11-06T08:19:05.201Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1407
File: src/components/AddWithdraw/DynamicBankAccountForm.tsx:459-475
Timestamp: 2025-11-06T08:19:05.201Z
Learning: In src/components/AddWithdraw/DynamicBankAccountForm.tsx, the street address field has a 35-character maximum length limit because the backend provider enforces this constraint, applicable to both US and Mexican addresses.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2025-08-26T15:25:53.328Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1132
File: src/app/[...recipient]/client.tsx:394-397
Timestamp: 2025-08-26T15:25:53.328Z
Learning: In `src/components/Common/ActionListDaimoPayButton.tsx`, the `handleCompleteDaimoPayment` function should not display error messages to users when DB update fails because the Daimo payment itself has succeeded - showing errors would be confusing since the payment was successful.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2025-06-22T16:10:53.167Z
Learnt from: kushagrasarathe
Repo: peanutprotocol/peanut-ui PR: 915
File: src/hooks/useKycFlow.ts:96-124
Timestamp: 2025-06-22T16:10:53.167Z
Learning: The `initiateKyc` function in `src/app/actions/users.ts` already includes comprehensive error handling with try-catch blocks and returns structured responses with either `{ data }` or `{ error }` fields, so additional try-catch blocks around its usage are not needed.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2024-10-25T11:33:46.776Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 484
File: src/components/Cashout/Components/Initial.view.tsx:273-274
Timestamp: 2024-10-25T11:33:46.776Z
Learning: In the `InitialCashoutView` component (`src/components/Cashout/Components/Initial.view.tsx`), linked bank accounts should not generate error states, and the `ValidatedInput` component will clear any error messages if needed. Therefore, it's unnecessary to manually clear the error state when selecting or clearing linked bank accounts.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2024-10-07T15:28:25.280Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 422
File: src/components/Request/Pay/Views/Initial.view.tsx:76-78
Timestamp: 2024-10-07T15:28:25.280Z
Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(estimatedGasCost, 3)` return strings, ensuring consistent return types for `calculatedFee`.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
🧩 Analysis chain@Hugo0, I'll perform an in-depth review of this PR. Let me gather the code changes first. 🏁 Script executed: Length of output: 1342 🏁 Script executed: Length of output: 29773 🏁 Script executed: Length of output: 43598 @Hugo0, I've completed an in-depth review of this PR. Here's my comprehensive analysis: ✅ Strengths1. Backwards CompatibilityThe OR condition (
2. Improved User ExperienceRemoving "In Argentina" from the message is appropriate since both CPF (Brazil) and CUIT (Argentina) are tax IDs used for bank account identification, making the error message country-agnostic and scalable. 3. Clear DocumentationThe inline comment at line 244 explicitly documents that 4. Proper Error Handling
|
… messages Update withdraw error handling: - Support both TAX_ID_MISMATCH (new) and CUIT_MISMATCH (old) error codes - Show country-specific message based on currency (Argentina/Brazil) - Clarify this is due to local regulations, not a Peanut limitation Related backend PR: peanutprotocol/peanut-api-ts#536
e7a903a to
fbe10d3
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @src/app/(mobile-ui)/withdraw/manteca/page.tsx:
- Around line 258-261: The current else branch only calls
setErrorMessage(result.message ?? result.error) leaving the user on the review
screen with a disabled button; update that branch to also transition the flow to
the failure state by calling setStep('failure') so users see the same recovery
options ("Contact Support", etc.) as other failure paths—modify the code around
the existing setErrorMessage call (the else handling where result.message ??
result.error is used) to invoke setStep('failure') immediately after setting the
error message.
🧹 Nitpick comments (1)
src/app/(mobile-ui)/withdraw/manteca/page.tsx (1)
244-253: LGTM! Backwards-compatible error handling for Brazil CPF.The implementation correctly handles both
TAX_ID_MISMATCHandCUIT_MISMATCHerror codes, dynamically derives the country name from the currency, and transitions to the failure state with appropriate messaging. The backwards compatibility ensures old cached responses continue to work.As noted in the PR review, consider these follow-up improvements:
Add error monitoring: Track tax ID mismatch events with metadata for support analysis:
if (result.error === 'TAX_ID_MISMATCH' || result.error === 'CUIT_MISMATCH') { + captureException(new Error('Tax ID mismatch detected'), { + extra: { errorCode: result.error, currency: currencyCode, hasBackendMessage: !!result.message } + }) const countryName =Type safety: Define error code constants to prevent typos and enable autocomplete:
// In constants file export const MANTECA_ERROR_CODES = { TAX_ID_MISMATCH: 'TAX_ID_MISMATCH', CUIT_MISMATCH: 'CUIT_MISMATCH', // ... } as constTest coverage: Add unit tests for the error handling paths (both error codes, backend message priority, and fallback behavior).
Based on learnings, Hugo0 often agrees with architectural improvements but defers them due to time constraints—consider tracking these as follow-up issues.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/app/(mobile-ui)/withdraw/manteca/page.tsx
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1094
File: src/components/AddWithdraw/DynamicBankAccountForm.tsx:279-279
Timestamp: 2025-08-14T08:02:26.705Z
Learning: For hotfixes in the peanut-ui codebase, prefer generic error messages over specific validation error details until the copy can be reviewed with the team, even when the validation functions return detailed error messages.
Learnt from: Hugo0
Repo: peanutprotocol/peanut-ui PR: 942
File: src/components/AddMoney/consts/index.ts:2151-2162
Timestamp: 2025-06-30T10:44:08.048Z
Learning: Hugo0 often agrees with refactoring suggestions but defers implementation due to time constraints, preferring to track improvements as follow-up issues when they're part of larger architectural changes.
📚 Learning: 2025-05-22T15:38:48.586Z
Learnt from: kushagrasarathe
Repo: peanutprotocol/peanut-ui PR: 869
File: src/app/(mobile-ui)/withdraw/page.tsx:82-88
Timestamp: 2025-05-22T15:38:48.586Z
Learning: The country-specific withdrawal route exists at src/app/(mobile-ui)/withdraw/[...country]/page.tsx and renders the AddWithdrawCountriesList component with flow="withdraw".
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2025-09-18T09:30:42.901Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1230
File: src/app/(mobile-ui)/withdraw/page.tsx:92-97
Timestamp: 2025-09-18T09:30:42.901Z
Learning: In src/app/(mobile-ui)/withdraw/page.tsx, the useEffect that calls setShowAllWithdrawMethods(true) when amountFromContext exists is intentionally designed to run only on component mount (empty dependency array), not when amountFromContext changes. This is the correct behavior for the withdraw flow where showing all methods should only happen on initial load when an amount is already present.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2025-08-14T14:42:54.411Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1094
File: src/utils/withdraw.utils.ts:181-191
Timestamp: 2025-08-14T14:42:54.411Z
Learning: The countryCodeMap in src/components/AddMoney/consts/index.ts uses uppercase 3-letter country codes as keys (like 'AUT', 'BEL', 'CZE') that map to 2-letter country codes, requiring input normalization to uppercase for proper lookups.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2025-08-26T15:25:53.328Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1132
File: src/app/[...recipient]/client.tsx:394-397
Timestamp: 2025-08-26T15:25:53.328Z
Learning: In `src/components/Common/ActionListDaimoPayButton.tsx`, the `handleCompleteDaimoPayment` function should not display error messages to users when DB update fails because the Daimo payment itself has succeeded - showing errors would be confusing since the payment was successful.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2024-11-18T21:36:11.486Z
Learnt from: jjramirezn
Repo: peanutprotocol/peanut-ui PR: 535
File: src/components/Claim/Claim.tsx:142-146
Timestamp: 2024-11-18T21:36:11.486Z
Learning: In `src/components/Claim/Claim.tsx`, external calls like token price fetching and cross-chain details retrieval are already encapsulated within existing `try...catch` blocks, so additional error handling may be unnecessary.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2025-10-02T15:23:01.513Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1266
File: src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx:46-57
Timestamp: 2025-10-02T15:23:01.513Z
Learning: In the withdraw flow at src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx, the points calculation query intentionally uses crypto.randomUUID() in the queryKey dependency array to bypass React Query caching, ensuring fresh points estimates on every render. This is the intended behavior.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2025-11-06T08:19:05.201Z
Learnt from: Zishan-7
Repo: peanutprotocol/peanut-ui PR: 1407
File: src/components/AddWithdraw/DynamicBankAccountForm.tsx:459-475
Timestamp: 2025-11-06T08:19:05.201Z
Learning: In src/components/AddWithdraw/DynamicBankAccountForm.tsx, the street address field has a 35-character maximum length limit because the backend provider enforces this constraint, applicable to both US and Mexican addresses.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
📚 Learning: 2025-06-22T16:10:53.167Z
Learnt from: kushagrasarathe
Repo: peanutprotocol/peanut-ui PR: 915
File: src/hooks/useKycFlow.ts:96-124
Timestamp: 2025-06-22T16:10:53.167Z
Learning: The `initiateKyc` function in `src/app/actions/users.ts` already includes comprehensive error handling with try-catch blocks and returns structured responses with either `{ data }` or `{ error }` fields, so additional try-catch blocks around its usage are not needed.
Applied to files:
src/app/(mobile-ui)/withdraw/manteca/page.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Deploy-Preview
| // @dev TODO: Should this call setStep('failure')? Currently user sees error on review | ||
| // screen but withdraw button is disabled and there's no "Contact Support" option. | ||
| // Funds are already at Manteca's address at this point. | ||
| setErrorMessage(result.message ?? result.error) |
There was a problem hiding this comment.
Valid TODO: Inconsistent error flow leaves users without recovery options.
The TODO correctly identifies a UX issue: when a generic error occurs after funds have been sent to Manteca, users remain on the review screen with a disabled withdraw button and no "Contact Support" option, unlike the tax ID mismatch and "Unexpected error" paths that transition to the failure state with recovery actions.
This affects all non-specific error cases (e.g., rate limiting, temporary API failures). For consistency and better UX, the else branch should also transition to the failure state:
Suggested fix
} else {
- // @dev TODO: Should this call setStep('failure')? Currently user sees error on review
- // screen but withdraw button is disabled and there's no "Contact Support" option.
- // Funds are already at Manteca's address at this point.
setErrorMessage(result.message ?? result.error)
+ setStep('failure')
}This change is outside the scope of the tax ID mismatch fix but should be addressed to provide users with consistent recovery options. Would you like me to open a follow-up issue to track this improvement?
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // @dev TODO: Should this call setStep('failure')? Currently user sees error on review | |
| // screen but withdraw button is disabled and there's no "Contact Support" option. | |
| // Funds are already at Manteca's address at this point. | |
| setErrorMessage(result.message ?? result.error) | |
| } else { | |
| setErrorMessage(result.message ?? result.error) | |
| setStep('failure') | |
| } |
🤖 Prompt for AI Agents
In @src/app/(mobile-ui)/withdraw/manteca/page.tsx around lines 258 - 261, The
current else branch only calls setErrorMessage(result.message ?? result.error)
leaving the user on the review screen with a disabled button; update that branch
to also transition the flow to the failure state by calling setStep('failure')
so users see the same recovery options ("Contact Support", etc.) as other
failure paths—modify the code around the existing setErrorMessage call (the else
handling where result.message ?? result.error is used) to invoke
setStep('failure') immediately after setting the error message.
|
@coderabbitai do a final review |
Problem
Brazilian users withdrawing via Manteca get a generic error instead of a user-friendly message when their bank account CPF doesn't match their identity.
Root Cause
Backend PR #533 only added CUIT (Argentina) mismatch detection. Brazil uses CPF, which wasn't handled. The backend is being updated to return
TAX_ID_MISMATCHfor both countries.Changes
Update withdraw error handling to support both error codes:
TAX_ID_MISMATCH(new - covers Argentina CUIT + Brazil CPF)CUIT_MISMATCH(old - backwards compatibility)Also removed "In Argentina" from fallback message since it now applies to multiple countries.
Testing
CUIT_MISMATCHstill handled correctlyRelated