Open L-Yeiser opened 6 years ago
We were able to match a failed upload with an the corresponding s3 Post. The Unknown Error
is triggered by a 400 incomplete body. It would be awesome if s3 error were passed to the upload Event Listeners. Also any ideas as to why we are getting this error would be amazing.
Hi @L-Yeiser thanks for the report. If you're unable to reproduce consistently in your environment you could try in a fork of ReactNativeBackgroundUploadExample for a minimal environment
Unfortunately the failure is intermittent. I have added a substantial amount of error logging and will be pushing a release out in the next few days. Will post more when we have that information.
@TSMMark we are still unable to reproduce issue but we are seeing it frequently. Looking through our sentry breadcrumbs it appears to occur after an Lost connection to background transfer service
error. Any idea why I would be seeing Lost connection
errors when connected to high speed wifi?
Sorry, I'm not sure. Maybe #83 will help you with handling offline though
Is there a thread limit? We often spawn 10+ uploads at once.
I'm seeing the same issue on iOS when running multiple uploads at the same time.
@superandrew213 @L-Yeiser I see... Are you able to reproduce the issue consistently in a minimal environment? Such as a fork of ReactNativeBackgroundUploadExample? Please post / link
Will look into it. I think it's a timeout issue.
@L-Yeiser do you get the completed event to fire?
Upload.addListener('completed', uploadId, (data) => {
console.log(data)
})
I'm getting this response from s3
Your socket connection to the server was not read from or written to within the timeout period. Idle connections will be closed.
I'm guessing since we are uploading multiple files some files get blocked and timeout.
For me the error event doesn't fire at all when this happens.
@superandrew213 the completed event fires when the upload completes but not when I get unknown error
- in those cases the error event does fire. Where are you capturing that s3
error? We have only seen a 400 incomplete body
error. We have carved out some time this week to dig into it.
@L-Yeiser for me the completed
event fires with responseCode
400 and responseBody
has timeout error.
At the moment, I am just listening for this error and restart the upload. On the second try it always succeeds.
Looking into this a little more with @L-Yeiser today, we found that the error is coming back from the NSURLSessionDataTask
and being caught here. It's an NSURLErrorUnknown error, which doesn't really offer any insight. At the time the error is caught, the HTTP response is nil.
@superandrew213 retrying the upload does not work in our case. ATM we are batching uploads in groups of three and retrying any failed upload five times before failing the process. These safe guards have lessened the impact of the bug but we are still seeing it.
The NSURLErrorUnknown is always proceeded by a NSURLErrorBackgroundSessionWasDisconnected error thrown from the same line.
@TSMMark I was able to reproduce this issue consistently on an iphone 7 from the example app posted above when attempting to upload large video. In the example app we just switched media
to multitype
in the react-native-image-picker
config. This issue may be related to https://github.com/Vydia/react-native-background-upload/issues/53 which was closed without a solution.
@TSMMark wondering if it would work to use NSURLSessionUploadTask
instead of NSURLSessionDataTask
? Counter to this line the docs make it sound like NSURLSessionUploadTask
is the correct class to use when uploading in the background. This PR is also using NSURLSessionUploadTask
. I admittedly have limited understanding of iOs development, but this error is our number one issue.
@L-Yeiser I'd be happy to make a PR that uses a different API for iOS uploading. But it will take me some time. Will you test it for me once I do it?
@StevePotter would be more then happy to test it out.
We are also seeing the Unknown Error
and lost connection to background transfer service
fairly often in our app. (See also #93 and #92 )
In our case it only happens when the app is send to the background and we try to trigger the data upload in the handleAppStateChange
function.
As far as I can tell these factors cause the error to appear more often:
I'm guessing that the upload process gets killed by the os to free up memory / processing power.
Like @L-Yeiser mentioned it seems like the NSURLSessionUploadTask
is meant for this scenario, but uploadTaskWithRequest
should already return that type.
Changing NSURLSessionDataTask *uploadTask;
to NSURLSessionUploadTask *uploadTask;
doesn't seem to have any effect. (Kind of expected)
@L-Yeiser I checked in the code and we are using the important calls to create the NSUrlSessionUploadTask
. We are just casting it as the base type for some reason. I'll fix that, but that's not going to change anything.
For non-multipart, we use https://developer.apple.com/documentation/foundation/nsurlsession/1411550-uploadtaskwithrequest?language=objc
There is another version of that function that also takes in a completion handler. That could avoid having to rely on the session's handler: https://github.com/Vydia/react-native-background-upload/blob/master/ios/VydiaRNFileUploader.m#L282
Maybe, just maybe, that would help. But I'm basically just shifting around APIs and doubt that'll actually fix anything. I might give it a shot but don't hold your breath. If you want to go for it, I'd be happy to give a few tips, or even a phone call.
@StevePotter thanks so much for looking into it. I can look into it a bit in the coming months
Hi guys, I am facing the same issue consistently throughout my app. If I upload relatively large videos or multiple videos at once and so on... Did you manage to find a solution and make it work? Any help would be appreciated!
We never did. We switched libraries and are forcing uploads when the app is active for the time being. We have some tech time scheduled to circle back to the issue in the next month.
Thank you for taking the time to reply to me, I appreciate it. I think I figured out a way to allow multiple video uploads at the same time (it is only allowing 2 and failing on the 3rd). I am testing it and trying to fix other issues before I submit a PR.
That would be amazing. Let me know if you want me to test a fork.
@L-Yeiser
We never did. We switched libraries and are forcing uploads when the app is active for the time being. We have some tech time scheduled to circle back to the issue in the next month.
Wich library do you use ? Is this library can handle large file upload ?
Thanks for your reply
any progress on the fix? I'm still getting "unknown error" when trying to upload a video that has more than 100mb on iOS.
What do you guys think of what @cristianoccazinsp pointed out in #155?
I was having some issues on iOS and ended up forking the repo and messing around with it to try and get it working... take whatever I'm about to say with a big grain of salt because this is literally the first time I've ever looked at Objective-C code and I'm a few months into my first React Native project.
The uploader uses uploadTaskWithRequest:fromFile to create the session task. Background sessions require the task to be created from a file URI, so this seems right. However, it never worked for me and I would find that every upload resulted in an empty 0 byte file uploaded to S3. I found some App Sandbox errors in my device console.
Sandbox: app_name(930) deny(1) file-issue-extension target:/private/var/mobile/Media/DCIM/102APPLE/IMG_2942.JPG class:com.apple.nsurlsessiond.readonly
Sandbox: nsurlsessiond(91) deny(1) file-read-metadata /private/var/mobile/Media/DCIM/102APPLE/IMG_2942.JPG
So what I'm guessing is happening is that the file upload is just failing to read the media contents and send them along to S3. It's just weird the upload still happened and everything appeared to work on the client side.
What I had to do was make a copy of the file I was uploading to a temporary location within my app sandbox, create the upload task with the temporary file path, and then clean up that temp file after the upload was complete. After that change I've been able to upload fairly large video files to S3 in the background without any issues.
I tried reading the file contents and using uploadTaskWithRequest:fromData but that failed every time the app would go into the background with Lost connection to background transfer service
. I also tried always using uploadTaskWithStreamedRequest and implementing the needNewBodyStream delegate, but that would also fail with Lost connection to background transfer service
every time the app went into the background.
I also found that attempting to use the multipart upload mode did seem to work as far as uploading a file goes, but S3 didn't understand what I was uploading and I'd find my files were stored in a raw data file format where you'd be able to open it, view the headers, see the content boundary strings, and a bunch of binary data. So that didn't really work out for me.
Hope this helps. I was at this for days...
I am getting following error while uploading a video in android {error: "Upload error", id: "938b77cb-0e6f-4191-87a0-7e50fab0d1b4"} It is successfully uploading a image file but not video file and below is my code example const userToken = await AsyncStorage.getItem('accessToken'); const tokenType = await AsyncStorage.getItem('tokenType'); const options = { url: CONST.API_URL+'demoUpload', path: path.replace('file://', ''), method: 'POST', field: 'upload_file', type: 'multipart', maxRetries: 2, // set retry count (Android only). Default 2 headers: { Accept: 'application/json', 'Content-Type': 'multipart/form-data', Authorization: tokenType + ' ' + userToken, }, // Below are options only supported on Android notification: { enabled: true }, useUtf8Charset: true }
Upload.startUpload(options).then((uploadId) => {
console.log('Upload started')
Upload.addListener('progress', uploadId, (data) => {
console.log(`Progress: ${data.progress}%`)
})
Upload.addListener('error', uploadId, (data) => {
alert(data.error);
console.log(`Error: ${data.error}%`)
console.log(data);
this.setState({isLoading: false});
})
Upload.addListener('cancelled', uploadId, (data) => {
console.log(`Cancelled!`)
})
Upload.addListener('completed', uploadId, async (data) => {
// data includes responseCode: number and responseBody: Object
console.log('Completed!');
let responseJson = JSON.parse(data.responseBody);
console.log('response saved');
console.log(responseJson);
})
}).catch((err) => {
console.log(err);
console.log('Upload error!', err)
})
Occasionally uploads fail with
Unknown Error
. We are using the library with a forked versionreact-native-image-crop-picker
which allows downloading assets from the cloud. The error occurs intermittently and seems to be an iOs only issue. Attempting the upload again with a the same media often works. We have been unable to find consistent reproduction steps. Is there a way to get a better error so we know where to start with this issue? Has anyone else come across the same thing?