React-pdf: Visiting react-pdf throws Unhandled rejection: DataCloneError in IE10 on Windows <10

Created on 29 Oct 2017  ·  28Comments  ·  Source: wojtekmaj/react-pdf

It looks like react-pdf is not compatible with IE11 and IE10 on Windows version 8.1 (tested through Browserstack). IE11 on Windows 10 does not have this problem. An Unhandled rejection: DataCloneError error is thrown. Tried it with several PDF's, including the react-pdf sample at http://projekty.wojtekmaj.pl/react-pdf/

I found this closed pdf.js issue which seems related. Any idea?

bug

Most helpful comment

@up209d That is not a good idea to import both entry files, and disabling worker won't work in React-PDF 4.x.

Would you check the newest beta if you're getting the same error?

All 28 comments

Uh-oh. This seems like something 100% PDF.js related. In such case, I can't help you :( I only could suggest a workaround, IE on 8.1 seemed to have multiple issues fixed by logging while using Admin account. But I don't know if that's gonna help in your specific case.

I will have another look. I also think this is pdf.js related, but the pdf.js demo viewer did not throw this error in IE11 on Windows 8.1. Tried a number of different pdf's with their demo viewer and they all open normally.

Hmm... Perhaps we're using some APIs that are not used by PDF.js demo viewer. I'll look for a virtual machine and have another look.

@michaeldzjap Do you perhaps have an error stack? That would be very helpful.

This is in IE11 on Windows 8.1 using Browserstack:

screen shot 2017-11-04 at 18 07 56
screen shot 2017-11-04 at 18 08 22

Doesn't give loads of useful information unfortunately, but it seems like it might be the worker that causes trouble.

I am getting a very similar problem when using react-pdf in IE10. I am getting the error:

"unhandled promise rejectionDataCloneError"

And the PDF is not rendering.

This error is occurring in IE10, using Windows 7 (this is an environment "spun-up" in SauceLabs)

Interestingly in the network info panel, the request being made returns a HTTP 304 result. This is most likely causing issues with PDF.js as it does not know where to get the "stored representation", even though this is the first time I am making the request!

@michaeldzjap Have you found a way to fix this issue? Also did you check your network info to see what response code you were getting? I don't want to have to re-write how I am getting the PDF data, so hopefully we can find a fix for this!

I haven't had the time yet to take a proper look at it. I wanted to try to see if not using a worker would solve this issue, since that seems to be the problem:

screen shot 2017-11-06 at 14 05 23

The request for the worker file doesn't change its status from (Pending...)

As a result of my own investigation, I found that the HTTP 304 response was not the issue.

The issue appears to be with the PDF web worker in IE10. If the web worker is disabled e.g.

import { Document } from 'react-pdf/build/entry.noworker';

Then the PDF gets rendered as expected.

Whilst this isn't the best solution from a performance point of view, it is a fix for IE 10. Code can be written to switch between webworker/no worker depending on the browser executing the JavaScript.

I can confirm that disabling the worker loads and renders a PDF correctly in my own viewer app built with react-pdf in IE10 on Windows 8.1 (tested through Browserstack). Although not ideal (switching on/off the worker based on some kind of browser/device detection algorithm), I guess the solution @8enSmith proposes is the only way to go.

I have the same issue, what webpack version are you guys using? I am still on 1.x.

@alphiii I am using Webpack 3.8.1. As @michaeldzjap and myself have said, this is an issue with IE and the web worker, not with Webpack.

Has anyone checked if this issue has been raised with the pdf.js devs yet?

I linked this earlier. Seems to be related, if not exactly the same problem.

@michaeldzjap Ah, I missed that! Good work in linking this issue to that.

Hey @michaeldzjap, thanks so much again for this report - I've had a look into this and it seems this is the problem when we're passing a file as base64. Will resolve this by handling decoding base64 myself before passing it to PDF.js. Expect it in version v2.4.1 :)

Published it right now. Check out v2.4.1!

@wojtekmaj Thanks! I tried just now with my viewer app and it is still not working for me unfortunately. Still the same issue; PDF doesn't load for some reason, although at least the worker script seems to be loading fine now. I also tried the react-pdf sample and it is also not loading (but maybe this needs to be rebuild?). Both cases were tested through Browserstack on Windows 8.1 in IE11.

I think in the case of my own viewer app it might be due to the fact that the file prop to Document is an URL that makes a GET request to a server to fetch the PDF, which in turn is returning a file stream with the contents of the PDF. Not sure if that is really a good approach anyway, but that is currently how my frontend app hooks into an already existing PHP based backend and it seems to work in all cases (well, except for Windows 8.1 obviously ;) ).

Anyway, thanks for all your hard work. The reason it still doesn't work for me is probably due to my specific setup. Hope I will have some time soon to investigate this more in depth.

Hey @michaeldzjap,
that's strange. Sample indeed fails for me, but test suite does not; the only difference between test suite and sample is that test suite is minimized, and the way the file is fetched.

And the latter is the key. Test suite, when you click "Use imported file", passes the file as Base64. What seems to fail at the moment on IE is simply passing an URL which our sample uses. Fetching a document this way fails on IE10 on Windows 8.1. I don't think I'm going to touch this as this is too fragile and I might break something on more modern browsers.

For your specific case, I'd suggest handling file fetching yourself and passing it as, for example, Uint8array.

If you come up with an idea on how to fix this bug on IE10 without affecting other browsers (i.e. without re-writing the whole document fetching engine that exists in PDF.js), I'd be more than happy to apply the fix.

I don't think I'm going to touch this as this is too fragile and I might break something on more modern browsers.

Yeah, I agree. If it would affect other more recent browsers then it would be worth the effort. For the moment my workaround is to simply set my entry point to react-pdf dynamically using OS detection. If it is Windows < 8.1 I am using the entry point with no worker, else an entry point with the worker enabled. Not very elegant, but easy enough and will do for my use case.

If you come up with an idea on how to fix this bug on IE10 without affecting other browsers

I will have a think about this. One solution could be to, as you suggest, fetch the source manually when the file prop is an URL, convert it to Uint8array and only then pass it to PDFJS.getDocument(). But since it seems the majority of browsers don't have an issue with a file prop that is a URL this approach will only add unnecessary overhead and increase loading times in the majority of cases (unless you include some form of OS/browser detection to only use this approach for specific older browsers). So I don't think this should be the responsibility of react-pdf. Maybe a note about this or a link to this issue in the documentation is sufficient.

On a side note; I've tried to enable/disable the worker using the setOptions function like so:

import bowser from 'bowser';
import { Document, Page, setOptions } from 'react-pdf/build/entry.webpack';
...
constructor(props) {
    setOptions({
        disableWorker: bowser.msie && bowser.windows && bowser.osversion <= 8.1
    })
}
...

which did not seem to work for me (i.e. same "error" with IE on Windows 8.1, PDF not loading). So instead I use this entry script

import bowser from 'bowser';

import Document from 'react-pdf/build/Document';
import Outline from 'react-pdf/build/Outline';
import Page from 'react-pdf/build/Page';

import { isLocalFileSystem, warnOnDev } from 'react-pdf/build/shared/util';

// Workaround for apparent worker problem with IE on Windows version <= 8.1
if (bowser.msie && bowser.windows && bowser.osversion <= 8.1) { // Don't user worker
    const pdfjs = require('pdfjs-dist/build/pdf.combined');
    require('pdfjs-dist/web/compatibility');

    pdfjs.PDFJS.disableWorker = true;
} else {    // Use worker
    if (isLocalFileSystem) {
        warnOnDev('You are running React-PDF from your local file system. PDF.js Worker may fail to load due to browser\'s security policies. If you\'re on Google Chrome, you can use --allow-file-access-from-files flag for debugging purposes.');
    }

    require('pdfjs-dist/webpack');
    require('pdfjs-dist/web/compatibility');
}

export {
    Document,
    Outline,
    Page
};

which does seem to work. Would you have any idea why setOptions() fails?

First of all, setOptions should be imported from the same entry file you're importing Document from, your example misses that. I'm assuming that in real code it's imported properly?

Secondly, looking at the code you must be using react-pdf <= v2.2.0, because v2.3.0 relies on PDF.js which ditched separate compatiblity.js file and opted for bundling it by default. Please make sure you're using the newest version.

Another thing I'd have a look on is where you set these options. Generally the sooner the better - it's crucial to set these options before rendering starts. So maybe try in file body instead of Class body, which would make it equal to this entry file you wrote?

First of all, setOptions should be imported from the same entry file you're importing Document from, your example misses that. I'm assuming that in real code it's imported properly?

Yes, I forgot to include that in my post. In the original code that gets imported from the same entry point. But perhaps that is the problem: importing from the webpack entry point, which in turn calls require('pdfjs-dist/webpack') and then setting disableWorker: true. Can't really imagine why that would be a problem, but for some reason it doesn't work (IE11, Windows 8.1). I tried calling setOptions() both outside of my class definition (but in the same file) and in the constructor of my class.

Secondly, looking at the code you must be using react-pdf <= v2.2.0, because v2.3.0 relies on PDF.js which ditched separate compatiblity.js file and opted for bundling it by default. Please make sure you're using the newest version.

Yes, wasn't aware this changed between v2.2.0 and v2.3.0. I updated my custom entry point to reflect the changes.

So in conclusion: my custom entry point works as expected, importing setOptions() from react-pdf/build/entry.webpack and then setting disableWorker: true before my class definition or in my class constructor does not. The only change between the two approaches is that for my custom entry point I use the react-pdf/build/entry.noworker entry point when choosing to disable the worker. Anyway, it is not a big deal really. The custom entry point way works fine for me, even though using setOptions() would be slightly cleaner.

Oh geeez I know now. I'm retarded. If you use webpack entry point then disabling worker will not work as the whole point of it is to pass the worker to PDF.js effortlessly using webpack's loader. So most likely disableWorker flag would get ignored. Hard to say really as PDF.js is severely lacking documentation

If my theory is correct, then replacing

const pdfjs = require('pdfjs-dist/build/pdf.combined');

with

const pdfjs = require('pdfjs-dist/webpack');

should break your code... 🤔

Ah yes. That is it probably. pdf.js sets the worker in its webpack config.

Linking for future reference as it might be interesting: mozilla/pdf.js#9196

I found it not working in IE11.(it's fine in chrome and Firefox)
1
2

I've tried to change 'import { Document } from 'react-pdf/dist/entry.webpack';' to
'import { Document, Page } from 'react-pdf';'
but still not work

In short, solution atm is sacrificing the worker on IE/Edge:

// Import the entry
import { Document, Page } from 'react-pdf/dist/entry';

// Check whether we are not in IE
if (!utils.isIE()) {
  // Setting up the worker here
  require('react-pdf/dist/entry.webpack');
}

@up209d That is not a good idea to import both entry files, and disabling worker won't work in React-PDF 4.x.

Would you check the newest beta if you're getting the same error?

The 4.2.0-beta fixed IE10 for me 🎉
When is it releasing?

4.2.0 will never happen - introduced breaking changes so 5.0.0 will be released instead. 5.0.0-beta.2 was out for a while now, feel free to use it :)

Was this page helpful?
0 / 5 - 0 ratings