-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[HOLD for payment 2024-12-30] BUG: Receipt is deleted if app is killed while request is in queue #51761
Comments
Triggered auto assignment to Contributor-plus team member for initial proposal review - @allgandalf ( |
Triggered auto assignment to @johncschuster ( |
From taking a quick look at what happens to the What I noticed instead is a 405 response from the BE regarding the Note: I also noticed a Onyx merge error once the call is being made when returning back online, most likely coming from the BE response in onyx data. I'd look into this from a BE perspective to see what happens there, if the receipt is indeed passed and why does the BE respond with error in this issue's case. I'm assuming it might have something to do with the scan being intrerupted by the user closing the app while offline, then getting back online and call being resumed from squential queue, since the BE response is error: no amount was passed. |
Hi, thanks for taking a look @ikevin127. There's a lot more context that I forgot to add to the issue description. I'll start adding that now. I'll also work on doing some backend testing to verify that the receipt file is not received in this case. I'm having a bit of trouble getting the iOS simulator to connect to my dev environment, which is why I haven't been able to gather that info yet. However, I'm pretty sure that's what's happening. |
The description is updated now. |
I deployed iOS: Native on a real device and was able to do some debugging, |
What were your conclusions from debugging? I see you crossed part out. |
@neil-marcellini It's confusing but here's what I found: The root cause does not seem related to the device saving the file temporarely but rather to this line -> where we save the source here: Lines 458 to 463 in bef062b
because in our case Then we have this part: Lines 840 to 849 in bef062b
where we build the What I noticed about function setMoneyRequestReceipt(transactionID: string, source: string, filename: string, isDraft: boolean, type?: string) {
if (isDraft) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {
receipt: {source, type: type ?? ''},
filename,
});
}
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {
receipt: {source, type: type ?? ''},
filename,
});
} Then when returning back online and transaction fails, we always get the ScreenRecording_11-04-2024.14-40-44_1.MP4This is the confusing part as I was not able to figure out what happens BE wise when returning back online and why changing |
@neil-marcellini thoughts on ^ |
Interesting, thanks for posting your findings. I managed to test this on dev with an iOS simulator. Of course I can't take a photo but choosing an image from the photo library had the same result. I had to leave the app killed for about a minute to reproduce the issue, which isn't shown in the video to save time. I confirmed by debugging the backend that the receiptFile is empty. I will try your suggested solution and see if that fixes it. ScanDeleted2024-11-06.at.12.47.20.mp4 |
I'm not quite sure I'm following. When requestMoney is called on the confirmation page the receiptFile is passed. App/src/pages/iou/request/step/IOURequestStepConfirmation.tsx Lines 500 to 503 in ab40264
If you trace that down to where the failure data is generated I'm pretty sure it all works. |
I added a suggestion about how we might store the photo in a non temp location. |
Hi, I am Michael (Mykhailo) from Callstack, an expert agency and I can work on this issue. |
Thanks so much. Please post a proposal for how you're planning to fix this. |
@rezkiy37 when can we expect a proposal for the fix? |
I am working on the proposal. I will post it next week. |
Heads up, I'll OOO next week. If you want a faster review you can ask @johncschuster to get another internal reviewer. |
friendly bump for the copy @NickTooker |
I think Neil's copy and reasoning are sound. Let's keep the same first sentence (didn't vs failed) which makes the entire message more casual/approachable IMO. Let's also re-add the CTA at the end to try again. |
@johncschuster, @neil-marcellini, @NickTooker, @rezkiy37, @allgandalf Whoops! This issue is 2 days overdue. Let's get this updated quick! |
No overdue. The PR has been approved and is waiting for merging. Also, I will work on the second PR to fix the receipt uploading (#52483 (comment)). |
♻️ Update: PR was merged |
Working on the blob issue. |
It seems like I've found a solution. Basically, I am going to recreate a blob before the request. There is a function App/src/libs/fileDownload/FileUtils.ts Lines 168 to 174 in 2e8f4fa
Video
IOS.mp4Screenshot and receipt
URL - https://www.expensify.com/receipts/w_4812412a80340a1e10eb45117c112ae80510bc1e.jpg Working on a PR. |
Thanks for the update @rezkiy37 |
Working on the PR - #54358. |
There are some troubles with building IOS and Android currently. So I am coding but hopefully, I will test it on Monday. |
yeah builds were failing, but if you merge main now, all builds should be successful! |
I've been able to launch IOS today. I am polishing the PR today. Also, I still want to figure out why the blob breaks down after the app refresh. |
The solution for this issue has been 🚀 deployed to production 🚀 in version 9.0.77-6 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue: If no regressions arise, payment will be issued on 2024-12-30. 🎊 For reference, here are some details about the assignees on this issue:
|
@allgandalf @johncschuster @allgandalf The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button] |
@johncschuster please remove the hold for payment label here, we are working on PR part 2 of this issue, thanks :) |
ProposalPlease re-state the problem that we are trying to solve in this issue.Submitting the scanned expense is errored when the user kills the app while the request is in the queue. What is the root cause of that problem?The app utilizes What changes do you think we should make in order to solve the problem?I propose reconstructing a blob of the receipt if the request is created while the user is offline. I am going to intercept the blob right there: Lines 162 to 167 in 52b4eca
I require an additional property ( Line 23 in 52b4eca
The draft implementation is if (key === 'receipt' && initiatedOffline) {
const {uri: path = '', source} = data[key] as File;
return import('./fileDownload/FileUtils')
.then(({readFileAsync}) => readFileAsync(source, path, () => {}))
.then((file) => {
if (!file) {
return;
}
formData.append(key, file);
})
.catch(() => {
console.debug('[dev] Error reading photo');
});
} I use the dynamic import because there is a circle-import issue (Slack). Draft PR - https://github.com/Expensify/App/pull/54358/files. What alternative solutions did you explore? (Optional)
|
I will look in detail at the proposal tomorrow, just thinking out loud, the new reconstructed blob will still be attached to the same |
Yes, right.
Not actually. We use the same image (path). We recreating the blob object to send the correct one. |
Ohh i re-read what you wrote, got it! thanks!!!, makes sense to me mostly but still i will review and let you know tomorrow and Merry Christmas 😄 |
Merry Christmas 🎄🎁 |
If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!
Version Number: v9.0.55-9
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught on HybridApp, is this reproducible on New Expensify Standalone?:
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: See the linked issue below
Expensify/Expensify Issue URL: https://github.com/Expensify/Expensify/issues/434533
Issue reported by: @neil Marcellini
Originally reported internally here
Slack conversation https://expensify.slack.com/archives/C049HHMV9SM/p1730315753190039
Action Performed:
Expected Result:
The receipt is uploaded and scanned correctly. If it fails for some reason, then the user is able to download the receipt.
Desired Result:
Store images captured with the in app camera to a non-temporary folder in the application folder within the file system. For example, store images in a folder
Receipts-Pending-Upload
under theNew Expensify
folder.We're still discussing in the thread linked below, but maybe after a receipt has been uploaded on the server, delete it from this folder.
Actual Result:
There is an error submitting the expense and no option to download the receipt. If the user dismisses this error then they permanently lose the receipt image.
Notes
I think this happens because we store the receipts in a /tmp/ folder which is cleared when the app is killed (E.g. file:///private/var/mobile/Containers/Data/Application/C5B31E5E-C6BD-4372-B1DF-D1326BDA7B28/tmp/9C8642AF-C0FF-44F9-988A-10B3A752B7A2.jpeg). It's a common nervous habit of iOS users to kill apps whenever they go to the home screen, so it's pretty realistic that this can happen, especially if the SequentialQueue gets a bit backed up.
More discussion in #quality.
Looks like if we upgrade react-native-vision-camera we can specify a path when taking the photo. Or we could manually move the file to our desired location, if upgrading vision camera is really difficult.
Workaround:
Try to take screen shots of the receipt images before dismissing the error and try re-uploading later. Not a very good workaround especially when users trust our app not to lose data.
Platforms:
Which of our officially supported platforms is this issue occurring on?
iOS Standalone, maybe others.
Screenshots/Videos
Add any screenshot/video evidence
OfflineReceiptLoss_10-30-2024.11-48-37_1.MP4
View all open jobs on GitHub
Issue Owner
Current Issue Owner: @johncschusterThe text was updated successfully, but these errors were encountered: