When a user's verification fails because we never captured an email, they land on the "we hit a snag, message support" screen with no button to fix it themselves. We already have the fix built (ProvideEmailStep saves an email and the BE re-runs submission), but this particular failure never routes there.
Real case from support
A user unchecked email consent, then tried to withdraw over bridge.ach_us. Verification failed with submission_failed / "No email captured from Peanut user record or Sumsub questionnaire — Bridge/Manteca customer payload cannot be built". They spent a weekend in support chat, got told to try Profile > Unlocked regions > LATAM, still saw no button, and an agent finally approved them by hand.
Where it breaks
deriveGate in src/utils/capability-gate.ts (around lines 212-223) only returns the self-serve provide-email state when the blocked rail carries a provide-email action. This user's rail was blocked without that action, so it fell through to blocked-rejection.
blocked-rejection maps to InitiateKycModal variant blocked (getKycModalVariant), whose only CTA is "Contact support" (src/components/Kyc/InitiateKycModal.tsx, getCta). No re-submit, no email field.
src/components/Kyc/ProvideEmailStep.tsx is exactly the recovery for this and is already wired into add/withdraw and home activation.
Suggested fix
- Backend: when submission fails only because email is missing, attach the
provide-email action to the blocked rail so the existing self-serve path shows up.
- Frontend fallback: if a blocked rail's reason points at a missing email, offer
ProvideEmailStep instead of the support-only modal, so we're not fully dependent on the BE flag.
When a user's verification fails because we never captured an email, they land on the "we hit a snag, message support" screen with no button to fix it themselves. We already have the fix built (
ProvideEmailStepsaves an email and the BE re-runs submission), but this particular failure never routes there.Real case from support
A user unchecked email consent, then tried to withdraw over
bridge.ach_us. Verification failed withsubmission_failed/ "No email captured from Peanut user record or Sumsub questionnaire — Bridge/Manteca customer payload cannot be built". They spent a weekend in support chat, got told to try Profile > Unlocked regions > LATAM, still saw no button, and an agent finally approved them by hand.Where it breaks
deriveGateinsrc/utils/capability-gate.ts(around lines 212-223) only returns the self-serveprovide-emailstate when the blocked rail carries aprovide-emailaction. This user's rail wasblockedwithout that action, so it fell through toblocked-rejection.blocked-rejectionmaps toInitiateKycModalvariantblocked(getKycModalVariant), whose only CTA is "Contact support" (src/components/Kyc/InitiateKycModal.tsx,getCta). No re-submit, no email field.src/components/Kyc/ProvideEmailStep.tsxis exactly the recovery for this and is already wired into add/withdraw and home activation.Suggested fix
provide-emailaction to the blocked rail so the existing self-serve path shows up.ProvideEmailStepinstead of the support-only modal, so we're not fully dependent on the BE flag.