Workbox: "NotSupportedError: ReadableStream uploading is not supported" errors in Safari

Created on 24 Oct 2018  Β·  12Comments  Β·  Source: GoogleChrome/workbox

Library Affected:
workbox-sw

Browser & Platform:
Safari 12 on iOS 12

Issue or Feature Request Description:
When submitting a form that is registered with a route, I get the following error:
"NotSupportedError: ReadableStream uploading is not supported"

Everything works perfectly on Android and Chrome desktop on my Mac.

Here is the javascript, I'm using to register the routes:

const bgSyncPlugin = new workbox.backgroundSync.Plugin('ppSortMagicQueue');

    workbox.routing.registerRoute(
        '/Home/_SaveGallery',
        workbox.strategies.networkOnly({
            plugins: [bgSyncPlugin]
        }),
        'POST'
    );

Here is the request info from the debugger Network tab:

Summary
URL: https://sortmagic.redacted.net/Home/_SaveGallery
Status: β€”
Source: β€”

Request
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: */*
Referer: https://sortmagic.redacted.net/
Origin: https://sortmagic.redacted.net
User-Agent: Mozilla/5.0 (iPad; CPU OS 12_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1
X-Requested-With: XMLHttpRequest

Response
No response headers

Request Data
MIME Type: application/x-www-form-urlencoded; charset=UTF-8
WebsiteId: 5140
EventID: 7671
EventName
token: Cl+ndF3l7owkH1+3bcO2AJQYB2gIfDtqt65uSDzoV2t8jeZZ+pf1ncOUn/1fntxv2lUS0T11AipCNgwUxiql7MGWyfDItQXY5tVsKYHWp/IByhrTJtZde1+E2t8IC+GE
GalleryName: jQKJ17Ij8
Password
X-Requested-With: XMLHttpRequest

**And here is the console output from Workbox:**

[Error] workbox – "Network request for '/Home/_SaveGallery' threw an error."
NotSupportedError: ReadableStream uploading is not supported
fetch
(anonymous function) β€” workbox-core.dev.js:1400
generatorResume
step β€” workbox-core.dev.js:14
(anonymous function) β€” workbox-core.dev.js:32
initializePromise
Promise
(anonymous function) β€” workbox-core.dev.js:11
(anonymous function) β€” workbox-strategies.dev.js:822
generatorResume
step β€” workbox-core.dev.js:14
(anonymous function) β€” workbox-core.dev.js:32
initializePromise
Promise
(anonymous function) β€” workbox-core.dev.js:11
generatorResume
step β€” workbox-core.dev.js:14
(anonymous function) β€” workbox-core.dev.js:32
initializePromise
Promise
(anonymous function) β€” workbox-core.dev.js:11
handleRequest β€” workbox-routing.dev.js:365
(anonymous function) β€” workbox-routing.dev.js:835
    _print (workbox-core.dev.js:132)
    (anonymous function) (workbox-core.dev.js:1407)
    generatorResume
    step (workbox-core.dev.js:14)
    (anonymous function) (workbox-core.dev.js:27)
    promiseReactionJob

Thanks for your help!

Browser Compatibility Bug workbox-routing

All 12 comments

The error is coming from this WebKit code.

https://stackoverflow.com/a/50952018/385997 has a workaround:

Safari doesn't seems to support fetch with a Request object having a POST method ; probably because now when you construct a Request object, the body is wrapped in a ReadableStream.

You may convert your Request object to a tuple of arguments:

const body = await request.clone().text();
const {cache, credentials, headers, integrity, mode, redirect, referrer} = request;
const init = {body, cache, credentials, headers, integrity, mode, redirect, referrer};
fetch(request.url, init);

@philipwalton, do you see any downsides to switching over to using that workaround when replaying queued requests, in order to ensure Safari compatibility?

Hmmm, but this workaround assumes the requests all have text bodies, no? Currently we're constructing all replayed requests with Blob bodies to support binary files and whatnot.

Ohβ€”I hadn't looked at the code, and assumed, based on the error, that it was just using request.body directly as the BodyInit, but I didn't realize it was currently using the blob() reader:

https://github.com/GoogleChrome/workbox/blob/b146d8d3c2db89fa51afc322049b9795894bb4f2/packages/workbox-background-sync/models/StorableRequest.mjs#L52-L54

I guess I'm curious as to what Safari considers a non-ReadableStream upload, in that case? Should we ask some folks more familiar with the Streams API?

Thanks for checking on this guys. Is there something I can do to work around this from my end or do I need to wait for an update in your code?

Hey guys! Good news I figured out the issue. While testing on another iOS device, everything worked as expected. I wanted to send you the debug info and after I connected the iPhone to my laptop via USB and started the Safari debugging console, submitted the form, the error occurred. After disconnecting, the post worked. I suspect the ReadableStream is used in the debugging process.

Please feel free to close this if you're satisfies with that solution. Thanks!

I'm happy to close in that case. We can revisit if someone else can trigger this outside of the debugging scenario you describe.

So, I notice this error today as well when looking at the JS console in Safari. It seems to be happening as part of the workbox-google-analytics package, which is using a NetworkFirst strategy and for some reason throwing a no-response WorkboxError.

@jeffposnick, any ideas?

screen shot 2018-11-09 at 9 57 48 pm

Note: this doesn't seem to be related to background sync, at least as far as I can tell.

Actually, it does appear like the problem is exactly as described in that Stack Overflow post. These are POST requests, so service worker in Safari doesn't appear to be able to replay them.

Since, all Google Analytics requests sent with navigator.sendBeacon() are all going to be POST requests, this seems like a relatively big problem...

I'm having this same problem with Safari v12 on OSX.

This is indeed not limited to Background Sync, as @philipwalton correctly noted above. It also occurs on a regular login POST form (via https://github.com/GoogleChrome/workbox/issues/2260):

Screen Shot 2019-10-30 at 14 48 34

I dug into this a bit more and found the following, using https://glitch.com/edit/#!/suave-beanie as a simple reproduction.

Generally speaking, Safari has no problem sending a POST request constructed with a body.

The problem, which was accurately identified in this comment on Stack Overflow, is that Safari's behavior changes based on whether or not the Request object is logged to the console before it's being sent. Apparently, whatever code is necessary to log it is enough to convert the underlying Request object into a ReadableStream, and that means it's no longer valid when sending the POST. Additionally, you apparently need to have to have the JS console open to trigger itβ€”either the main console or the dedicated service worker console, depending on which context is doing the logging.

(This sounds like a bug that should be reported against WebKit, because I can't imagine that's ideal behavior.)

workbox-routing will log the Request object prior to passing it to fetch() at:

https://github.com/GoogleChrome/workbox/blob/194cdeb63d5abb21490f88f01f02f4bcf7e6d54b/packages/workbox-routing/Router.mjs#L200-L204

We should either remove that logging statement, or alternatively only log when it's GET request or when we know there's no body.

To summarize, this is a real bug that you can encounter in Safari for any request with a body that is handled by workbox-routing, but only if

  • you are using the dev bundles of Workbox which triggers extra logging
  • you have the Safari service worker debugger console open prior to the request is being sent

I've filed https://bugs.webkit.org/show_bug.cgi?id=203617 to track the issue in Safari.

Was this page helpful?
0 / 5 - 0 ratings