Skip to content
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

queue.replayRequests() fails with TypeError: Failed to execute 'clone' on 'Request': Request body is already used #1984

Closed
davidka opened this issue Mar 25, 2019 · 3 comments · Fixed by #2014

Comments

@davidka
Copy link

davidka commented Mar 25, 2019

Library Affected:
workbox.backgroundSync.Queue. (Workbox 4.1.1)

Browser & Platform:
Google Chrome v73.0.3683.86 macOS

Issue or Feature Request Description:
When queue.replayRequests() is called and the server is still down, it throws the following error and removes one item from the queue even if it wasn't synced.

sw.js:132 TypeError: Failed to execute 'clone' on 'Request': Request body is already used
    at d.g (Queue.mjs:176)
    at d.unshiftRequest (Queue.mjs:140)
    at d.replayRequests (Queue.mjs:246)

This is the code to register a route for background sync:

  const queue = new workbox.backgroundSync.Queue('myQueue')

  const addEventRoute = new workbox.routing.Route(
    ({ url }) => url.pathname === '/api/add',
    async args => {
      try {
        await fetch(args.event.request.clone())
      } catch (err) {
        console.error(err)
        queue.pushRequest(args.event)
      }
    },
    'POST'
  )

  workbox.routing.registerRoute(addEventRoute)

  self.addEventListener('sync', async ev => {
    try {
      await queue.replayRequests()
    } catch (e) {
      console.error(e)
    }
  })

When I try to manually trigger the sync from the UI with:

<Button
   variant="contained"
   onClick={() => navigator.serviceWorker.ready.then(reg => reg.sync.register('syncEvents'))}
>
sync
</Button>

it fails and removes the oldest entry from the queue.
The sync works well, when the server is reachable again but not when it is still down.

@syncai
Copy link

syncai commented Mar 25, 2019

Even if your endpoint is down it workbox is going to replay the request and pop it off the queue, regardless of the return code. I'm currently working around this too, editing the onSync logic based on this post about backgroundSync in workbox v4:

#1710

Here is my code. I'm throwing a network error because it seems to be the only one allows me to re-queue the request properly

  • made an edit, the last code block was a little buggy
const collectQueue = new workbox.backgroundSync.Queue('medsinc-collect', {
  maxRetentionTime: 60 * 24 * 30,
  onSync: async({ queue }) => {
    let entry;
    while (entry = await queue.shiftRequest()) {
      try {
        let clone = entry.request.clone()
        let response = await fetch(clone)
        if (!response.ok) {
          throw new Error()
        }
      }
      catch (e) {
        await queue.unshiftRequest(entry);
        throw {
          name: 'NetworkError',
          message: 'Server Not Available'
        }
        return
      }
    }
  }
});

@similicious
Copy link

I'm experiencing the same issue in the Chrome on Android (73.0.3683.90):

Uncaught (in promise) TypeError: Failed to execute 'clone' on 'Request': Request body is already used
    at Queue._addRequest (Queue.mjs:176)
    at Queue.unshiftRequest (Queue.mjs:140)
    at Queue.replayRequests (Queue.mjs:246)

The exact same code works in Chrome on Windows (both 73.0.3683.86 and 73.0.3683.103).

My service worker code is as simple as this:

const bgSyncPlugin = new workbox.backgroundSync.Plugin('tag', {
  maxRetentionTime: 24 * 60 // Retry for max of 24 Hours
});

workbox.routing.registerRoute(
  new RegExp('.+\/a\/b'),
  new workbox.strategies.NetworkOnly({
    plugins: [bgSyncPlugin]
  }),
  'POST'
);

@philipwalton
Copy link
Member

Thanks for the report, I've looked into it and it seems there's a place we're not cloning the request before re-fetch()-ing it. And since our tests weren't sending the request to a real server, they weren't reporting the error.

This should be fixed in #2014.

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

Successfully merging a pull request may close this issue.

5 participants