Skip to content

[Payment due @abzokhattab] Show temporary retry-later message for 531 broken card connection - #98672

Merged
youssef-lr merged 18 commits into
mainfrom
tgolenViaClaude/bank-error-531-messaging
Sep 3, 2026
Merged

[Payment due @abzokhattab] Show temporary retry-later message for 531 broken card connection#98672
youssef-lr merged 18 commits into
mainfrom
tgolenViaClaude/bank-error-531-messaging

Conversation

@tgolen

@tgolen tgolen commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

When a company-card connection returns scrape code 531 ("expected but unusable response, retry later"), the expense previously showed the generic broken-connection RTER message telling the user to fix their card. Code 531 is temporary and resolves on its own, so that message is misleading.

This PR maps the new backend RTER violation type brokenCardConnection531 to its own copy in BrokenConnectionDescription: "Receipt pending due to a temporary bank issue. Please try again later." The message is added to all languages.

This depends on the backend emitting brokenCardConnection531, which ships in the companion Auth PR: https://github.com/Expensify/Auth/pull/23728

image image

Fixed Issues

$ https://github.com/Expensify/Expensify/issues/671466
PROPOSAL:

Tests

The brokenCardConnection531 violation is emitted by the companion Auth PR (not yet deployed), so use Debug mode to inject the violation and verify the copy renders:

  1. Go to Account > Troubleshoot and enable Debug mode.
  2. Open any expense on a report, open the report's Details page, and tap Debug to open the Debug Report page.
  3. Tap the button to open the transaction (page titled "Debug - Transaction").
  4. Open the Transaction Violations tab and tap Create.
  5. Replace the JSON with:
    {
        "type": "violation",
        "name": "rter",
        "data": {
            "rterType": "brokenCardConnection531"
        }
    }
  6. Tap Create, then return to the expense.
  7. Verify the violation reads: "Can't auto-match receipt due to a temporary bank issue. Please try again later."
  8. Change the injected rterType back to brokenCardConnection and verify the existing broken-bank-connection copy renders instead (no regression).
  9. Verify that no errors appear in the JS console.

You can also run the automated tests:

  • npx jest tests/unit/ViolationUtilsTest.ts -t getViolationTranslation
  • npx jest tests/ui/BrokenConnectionDescriptionTest.tsx

Offline tests

The violation copy is rendered from local Onyx data with no network dependency. With the device offline, repeat the Tests steps above and verify the 531 copy still renders correctly.

QA Steps

Same as tests — the Debug-mode steps above can be run on staging. The new copy is otherwise dormant until the linked Auth change is deployed, at which point cards with scrape code 531 surface it in the normal flow.

You can ping @tgolen to QA this.

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari image

Map the new brokenCardConnection531 RTER violation type to its own copy
telling the user this is a temporary bank issue to retry later, instead
of the generic broken-connection message.
@OSBotify

This comment has been minimized.

@tgolen tgolen changed the title Show temporary retry-later message for 531 broken card connection [No QA] Show temporary retry-later message for 531 broken card connection Aug 14, 2026
@tgolen tgolen added the InternalQA This pull request required internal QA label Aug 14, 2026
The main expense violation message comes from the violations.rter
translation (via ViolationsUtils.getViolationTranslation), not only from
BrokenConnectionDescription. Add a 531 branch there in every language so
the temporary retry-later copy shows instead of falling through to the
wrong message, and cover it with a getViolationTranslation unit test.
@OSBotify

This comment has been minimized.

Use the same 'Can't auto-match receipt due to a temporary bank issue.
Please try again later.' wording for both the rter violation message and
the brokenConnection531Error header copy, so the two surfaces show one
consistent message.
@OSBotify

This comment has been minimized.

531 was missing from the broken-connection classifiers, so a 531
violation was treated as a generic pending RTER (showing 'Awaiting merge
with card transaction.') instead of a broken connection. Add 531
alongside 530 in isBrokenConnectionViolation and hasPendingRTERViolation,
and in the MoneyRequestHeader and report status bar broken-connection
lookups, so shouldShowBrokenConnectionViolation is true and the 531 copy
shows. Covered by a shouldShowBrokenConnectionViolation unit test.
@codecov

codecov Bot commented Aug 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.

Files with missing lines Coverage Δ
src/CONST/index.ts 91.07% <ø> (ø)
src/components/BrokenConnectionDescription.tsx 62.50% <100.00%> (+62.50%) ⬆️
src/libs/TransactionUtils/index.ts 92.25% <100.00%> (+0.20%) ⬆️
src/components/MoneyRequestHeader.tsx 0.00% <0.00%> (ø)
...c/components/MoneyReportHeaderStatusBarSection.tsx 1.58% <0.00%> (-0.06%) ⬇️
src/hooks/useMoneyReportHeaderStatusBar.ts 0.00% <0.00%> (ø)
... and 14 files with indirect coverage changes

@tgolen
tgolen marked this pull request as ready for review August 14, 2026 21:31
@tgolen
tgolen requested review from a team as code owners August 14, 2026 21:31
@melvin-bot
melvin-bot Bot requested review from abzokhattab and heyjennahay and removed request for a team August 14, 2026 21:31
@melvin-bot

melvin-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

@abzokhattab Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot
melvin-bot Bot removed the request for review from a team August 14, 2026 21:31

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4456a9f543

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/libs/TransactionUtils/index.ts Outdated
@abzokhattab

Copy link
Copy Markdown
Contributor

@MelvinBot @codex review the PR and check for regressions, breaking changes or bugs

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 4456a9f543

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@MelvinBot

Copy link
Copy Markdown
Contributor

🤖 Reviewed for regressions / breaking changes / bugs. The change is small, additive, and well-tested — the new brokenCardConnection531 type is threaded through everywhere 530 lives, plus unit + UI tests cover the copy. No breaking changes to existing 530/base flows. One inconsistency is worth confirming before merge, and there's a minor copy note.

🟡 531 is added to the personal-card suppression logic, but 530 is not

In MoneyRequestHeader.tsx:131-134 and useMoneyReportHeaderStatusBar.ts:125-128, the brokenConnectionError find now matches BROKEN_CARD_CONNECTION || BROKEN_CARD_CONNECTION_531 — but not _530. That find drives the "if it's a personal card, hide the header status bar" branch (return undefined).

Consequence: for a personal card with a 531 violation on an open/submitted report, the report-header status bar is suppressed entirely, whereas the same scenario with 530 keeps showing the status bar. Everywhere else in this PR (BrokenConnectionDescription, isBrokenConnectionViolation, hasPendingRTERViolation, all language getViolationTranslation branches) 531 is treated identically to 530.

Since 530 and 531 are both "temporary, self-resolving" scrape codes with their own dedicated copy, I'd expect 531 to mirror 530 here — i.e. not be added to these two finds. If the intent really is to suppress the header for personal-card 531 (matching base broken-connection behavior), that's fine, but then 530 looks like the odd one out. Either way the two codes currently behave differently in the header. Worth a deliberate decision.

The transaction-level violation message still renders for personal-card 531 (the 531 branch returns before the isPersonalCard block in getViolationTranslation), so this only affects the report-header status bar — not a total regression, just an inconsistency.

Why this is the only spot 531 ≠ 530

I compared every non-language reference to _530 vs _531:

🟢 Minor: status-bar copy wording

brokenConnection531Error in en.ts:9987 is "Can't auto-match receipt due to a temporary bank issue. Please try again later.", whereas the sibling brokenConnection530Error uses the shorter "Receipt pending due to broken bank connection". The PR description also quotes the copy as "Receipt pending due to a temporary bank issue…", which doesn't match what's in the code. Not a bug — just confirm which wording marketing/design approved, since 531 reuses the long getViolationTranslation string as its status-bar label rather than a short "pending" phrasing like 530.

✅ Looks good

  • CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531 added cleanly.
  • Copy added to all 12 locale files with correct per-locale typography; the new 531 strings are grammatically sound (including nl, where the pre-existing 530 line has an unrelated typo not touched here).
  • getViolationTranslation orders the 531 branch before the isPersonalCard block, so it can't be shadowed. ✅
  • Included tests (ViolationUtilsTest, BrokenConnectionDescriptionTest, TransactionUtilsTest) assert the exact en string and match en.ts. ✅
  • Purely local/Onyx-driven copy — no new network dependency, offline-safe as described.

Reply with @MelvinBot <feedback> if you'd like me to dig further into the header suppression behavior or anything else.

@abzokhattab

Copy link
Copy Markdown
Contributor

Should we wait for the backend to be shipped?

@tgolen

tgolen commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

@abzokhattab No, I'd actually perfer to roll this one out first. It won't be testable yet until the backend change is done, but I don't want to change the backend until the frontend can support it.

@abzokhattab

Copy link
Copy Markdown
Contributor

The copy mapping looks correct. My concerns are with the last commit, which reclassifies 531 as a broken connection rather than a pending RTER.

1. Multi-expense reports render no status bar. Excluding 531 from hasPendingRTERViolation makes hasAllPendingRTERViolations false while shouldShowBrokenConnectionViolation becomes true, so shouldShowStatusBar is true and next-step content is suppressed. But the broken-connection branch is gated on transaction, which comes from getOneTransactionThreadReportID and is undefined once a report has a second expense. statusBarType stays undefined, so MoneyReportHeaderMoreContent returns null where we previously showed "Pending match with credit card". I confirmed the three predicates directly: for two transactions each carrying a 531 with pendingPattern, allHavePendingRTERViolation is false and shouldShowBrokenConnectionViolationForMultipleTransactions is true; with a generic pendingPattern RTER the former is true. Same as the Codex P2. Pre-existing for 530, newly reachable for 531.

2. 531 in the personal-card lookup. In MoneyRequestHeader and useMoneyReportHeaderStatusBar, brokenConnectionError is used only for cardID and the personal-card suppression, on the basis that the "fix the card" link appears elsewhere. 531 has no such link, so this only removes information — a personal card with a 531 shows nothing in the header. 530 is excluded from the same lookup. Suggest dropping 531 from both find calls; BrokenConnectionDescription already renders the correct copy on fall-through.

3. Three further behavior changes, none in the test plan. hasPendingUI now returns false for 531, so the transaction preview and the chat report preview both lose their "Pending match" label, and useConfirmPendingRTERAndProceed proceeds straight through on submit/approve instead of offering to mark as cash. Consistent with how 530 behaves, but a "retry later" state arguably belongs with pending match. Could we get a product decision rather than having this fall out of the reclassification?

4. Does Auth #23728 set pendingPattern on 531? hasPendingRTERViolation requires it, so if Auth doesn't set it the new exclusion is unreachable and 1–3 are moot.

Tests. No coverage for the hasPendingRTERViolation exclusion, either header hook, or 530/531 precedence in BrokenConnectionDescription. The mocked useTransactionViolations also bypasses getVisibleTransactionViolations, so the test cannot catch a 531 filtered out by shouldShowViolation. Seeding Onyx would exercise the real path.

Minor.

tgolen added 2 commits August 24, 2026 11:36
The report status bar's broken-connection branch required a single
transaction, so a multi-expense report whose transactions all have a
broken-connection violation showed no status and suppressed the next
step. Trigger the branch on shouldShowBrokenConnectionViolation and fall
back to any report transaction with a broken connection to drive the
description. Export isBrokenConnectionViolation for the status bar
section.
…sion

- Remove 531 from the MoneyRequestHeader and report status bar broken
  connection lookups; that lookup only drives personal-card suppression,
  and 531 (like 530) has no fix link, so it should fall through to render
  the copy instead of being hidden.
- Remove the now-dead 531 exclusion in hasPendingRTERViolation; 531
  violations never carry pendingPattern, so the exclusion was unreachable.
- Use informal 'du' in the German 531 copy to match the surrounding
  strings.
- Add a 530/531 precedence test to BrokenConnectionDescription.
@tgolen

tgolen commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review — addressed across d0ec9ba and e7a46c4.

#1 (multi-expense status bar): Fixed. The broken-connection branch in useMoneyReportHeaderStatusBar now triggers on shouldShowBrokenConnectionViolation instead of the single-transaction guard, and MoneyReportHeaderStatusBarSection falls back to any report transaction whose violations include a broken connection to render the description. This applies to 530/reauth as well.

#2 (personal-card lookup): Done — dropped 531 from the find in both MoneyRequestHeader and useMoneyReportHeaderStatusBar. 531 now falls through to BrokenConnectionDescription like 530, so a personal-card 531 is no longer hidden.

#3 (product decision): Deliberate call — 531 stays classified as a broken connection, consistent with 530. The loss of the pending-match label and the mark-as-cash offer is the intended behavior for this state, not an accidental side effect of the reclassification.

#4 (pendingPattern): Correct — Auth #23728 does not set pendingPattern on 531, so the hasPendingRTERViolation exclusion was unreachable. Removed it.

Tests: Added a 530/531 precedence case to BrokenConnectionDescription. Good call that the mocked useTransactionViolations bypasses getVisibleTransactionViolations — noted as a follow-up to seed Onyx and exercise the header hooks against the real path.

German: Switched the 531 copy to informal "du" to match the surrounding strings.

🤖 Posted by Claude (an AI agent) on behalf of the user.

@MelvinBot

Copy link
Copy Markdown
Contributor

Re-review — latest changes look good, and verified live ✅

The two new commits since my last pass resolve the mixed-card suppression finding cleanly:

  • ac62f89 / fc2aa54 replace the single "first broken-connection violation" check with shouldSuppressBrokenConnectionStatus, which now suppresses the report status only when every broken-connection violation is a personal card and never for 530/531. That's the right fix: a report mixing a personal card with a company-card or retry-later violation keeps its actionable status instead of being swallowed — which addresses abzokhattab's mixed-expense report note. The added useMoneyReportHeaderStatusBarTest.ts covers both the retry-later and all-personal cases.

Live test: pass — injecting a rter / brokenCardConnection531 violation via Debug mode rendered the new copy verbatim, and reverting rterType to brokenCardConnection restored the original copy with no regression.

Step Status Observation
Enable Debug mode at Account > Troubleshoot ✅ pass Debug mode switch toggled on, distinct from the Sign out row
Reach Debug Report page from expense > Details > Debug ✅ pass Submitted the expense as a P2P IOU (RTER only renders when the viewer is the submitter), then opened Debug - Report
Open Debug - Transaction > Violations > Create ✅ pass Reached the create-violation JSON editor
Inject rter / brokenCardConnection531 payload and save ✅ pass Violations tab listed the new violation / rter row
531 copy reads "Can't auto-match receipt due to a temporary bank issue. Please try again later." ✅ pass Banner rendered the string verbatim
Revert rterType to brokenCardConnection → original copy, no regression ✅ pass Banner reverted to the broken-bank-connection copy, no 531 text
No JS console errors ⚠️ n/a The web tooling can't read the browser console; no error dialogs, crashes, or broken UI observed
Screenshots

Debug mode toggled on in Account > Troubleshoot

Debug mode toggled on in Account > Troubleshoot

Expense banner reading the new 531 copy

Expense banner reading the new 531 copy: Can't auto-match receipt due to a temporary bank issue. Please try again later.

Expense banner reverted to the original copy after editing rterType back

Expense banner reverted to the original broken-bank-connection copy after editing rterType back

No further blocking concerns from me — the copy inconsistency and translation-churn items from the earlier pass were already confirmed as intended (Polyglot Parrot output) and are non-blocking.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor

The latest commit (fc2aa54) was just re-reviewed and live-verified a few minutes ago — see that re-review here. Nothing has changed on the branch since, so re-running the full pass would only repeat it. Quick recap of where things stand:

  • Mixed-card suppression finding: resolved. ac62f89 / fc2aa54 replace the "first broken-connection violation" check with shouldSuppressBrokenConnectionStatus, which suppresses the report status only when every broken-connection violation is a personal card, and never for 530/531. This covers abzokhattab's mixed-expense report note, with a new useMoneyReportHeaderStatusBarTest.ts regression case.
  • Live test passed — injecting rter / brokenCardConnection531 via Debug mode rendered the new copy verbatim, and reverting rterType to brokenCardConnection restored the original copy with no regression.
  • Earlier items are non-blocking — the non-English churn is confirmed Polyglot Parrot output, and the 531 copy wording was confirmed as intended.
  • CI: the only red check is Check independent approval (waiting on a reviewer approval, not a code failure); everything else is green.

No further blocking concerns from me. If you push a new commit, tag me again and I'll re-verify against it.


view run

@abzokhattab

Copy link
Copy Markdown
Contributor

i think codex reviews are still valid .. what do you think @tgolen

@tgolen

tgolen commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

@abzokhattab Thanks! I haven't looked into them yet. I am hoping to have time tomorrow to make sure I understand them and then I'll respond.

@abzokhattab abzokhattab 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.

LGTM 🚀🚀 Thanks for covering the raised issues

@melvin-bot
melvin-bot Bot requested a review from youssef-lr September 2, 2026 20:51
@melvin-bot

melvin-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown

@youssef-lr Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot melvin-bot Bot changed the title Show temporary retry-later message for 531 broken card connection [Payment due @abzokhattab] Show temporary retry-later message for 531 broken card connection Sep 2, 2026
@melvin-bot

melvin-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown

🎯 @abzokhattab, thanks for reviewing and testing this PR! 🎉

A payment issue will be created for your review once this PR is deployed to production.
E/E issue linked to the PR - https://www.github.com/Expensify/Expensify/issues/671466.

If payment is not needed (e.g., regression PR review fix etc), react with 👎 to this comment to prevent the payment issue from being created.

@tgolen

tgolen commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

still trying to get the Jest test to pass 😅

@tgolen

tgolen commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

OK, looks like that's passing now and this is ready for final review. Thanks @abzokhattab!

@youssef-lr
youssef-lr merged commit ce33920 into main Sep 3, 2026
43 of 44 checks passed
@youssef-lr
youssef-lr deleted the tgolenViaClaude/bank-error-531-messaging branch September 3, 2026 00:54
@OSBotify

OSBotify commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

🚧 youssef-lr has triggered a test Expensify/App build. You can view the workflow run here.

@OSBotify

OSBotify commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/youssef-lr in version: 9.4.70-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@MelvinBot

Copy link
Copy Markdown
Contributor

Yes, help site changes are required. Draft PR: #100339

This PR adds a new user-facing violation message — “Can't auto-match receipt due to a temporary bank issue. Please try again later.” — and the help site only documented broken-connection messaging that tells people to go fix the card. Anyone who searches the new wording currently lands on articles that tell them to reconnect a feed that isn't actually broken, which is the exact confusion the new copy was written to remove.

What the docs PR changes (two articles, both under docs/articles/new-expensify/connect-credit-cards/):

Article Change
Fix-a-Broken-Company-Card-Feed-Connection.md New ## How to tell whether a receipt matching message needs action section listing each receipt matching message a Workspace Admin can see and whether it requires reconnecting the feed; new FAQ entry for the temporary bank issue message; keywords and internalScope updated
Manage-Personal-Cards.md Same new section for the personal card message variants; new FAQ entry; keywords updated
How the copy was sourced and verified

Every quoted message is copied verbatim from src/languages/en.ts on this PR's branch, so the help site matches what actually renders — including the pre-existing 530, plain broken-connection, and re-authentication variants that were also undocumented and sit right next to the new one.

The personal card article uses the personal-card wording (Can't auto-match receipt due to broken card connection., Reconnect, Fix the card) and the company card article uses the admin/member wording (Bank connection broken. Reconnect to match receipt, Ask an admin to reconnect to match receipt.), matching the branching in the rter translation.

UI labels used in the new copy were verified against the current app UI rather than assumed: Account, Wallet, Cards, and Company cards (lowercase c in cards — not Company Cards).

Authored against docs/HELPSITE_NAMING_CONVENTIONS.md, docs/HELP_AUTHORING_GUIDELINES.md, and docs/TEMPLATE.md: one # title plus # FAQ, ## only below it, every new heading task-based and starting with an action verb or question word, and UI labels bolded in exact Sentence case.

What I deliberately did not document

This PR also reworks the report-level status suppression (shouldSuppressBrokenConnectionStatus / getUnsuppressibleBrokenConnectionTransactionID in src/libs/TransactionUtils/index.ts) so 530 and 531 statuses are no longer swallowed by the personal-card suppression. That is internal rendering logic with no distinct user-facing string, so it needs no help site coverage.

@tgolen, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR Ready for review


view run

@OSBotify

OSBotify commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/youssef-lr in version: 9.4.72-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@MelvinBot

Copy link
Copy Markdown
Contributor

Yes — help site changes are required. Draft PR: #100363

This PR adds a user-facing message that the help site doesn't cover: "Can't auto-match receipt due to a temporary bank issue. Please try again later." Anyone who searches that phrase today lands on the broken-connection articles, which tell them to reconnect a card that isn't actually broken.

What I changed

Article Change
Fix-a-Broken-Company-Card-Feed-Connection.md New section How to recognize a temporary bank issue on a company card expense + FAQ entry
Manage-Personal-Cards.md New section How to tell a temporary bank issue from a broken personal card connection + FAQ entry

Both say the connection is still valid, no action is needed, and Expensify retries automatically. keywords and internalScope updated for retrieval.

How I mapped the code to the docs
  • The new copy applies to members and Workspace Admins, and to company cards and personal cards — the 531 branch in src/languages/en.ts is checked before any isPersonalCard / isAdmin branching.
  • The 531 status is never suppressedshouldSuppressBrokenConnectionStatus in src/libs/TransactionUtils/index.ts returns false for 530 and 531, so the message stays on the expense and in the expense report header. That's why the personal-cards article now contrasts it with the ordinary broken connection violation.
  • I used the copy from the code (violations.brokenConnection531Error), not the phrasing in this PR's description — the description says "Receipt pending due to a temporary bank issue", while the shipped string is "Can't auto-match receipt due to a temporary bank issue. Please try again later." Worth a glance in case the description is the intended wording.
  • No article covers the personal-card suppression refinement in this PR (company-card violations now surface to admins/approvers even when mixed with personal-card ones). That's an internal correctness fix with no separate user-facing message, so I left it undocumented.

UI labels used in the new copy — Company cards, Wallet, Fix card — were verified against the live web UI. The 531 message itself couldn't be reproduced live because the backend change (Expensify/Auth#23728) isn't deployed yet, so the copy is quoted from en.ts.

@tgolen, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR Ready for review


view run

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

Labels

InternalQA This pull request required internal QA

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants