playwright icon indicating copy to clipboard operation
playwright copied to clipboard

[BUG] "NS_BINDING_ABORTED" error in Firefox

Open wentwrong opened this issue 2 years ago • 36 comments

Context:

  • Playwright Version: 1.30.0
  • Operating System: Mac/Ubuntu
  • Node.js version: 18.12.1
  • Browser: Firefox

Code Snippet

See repository with minimal reproducible example: https://github.com/wentwrong/pw-firefox-ns-binding-aborted

Describe the bug

When you navigate to page A and then immediately navigate to page B (using page.goto), if page A asynchronously navigates itself to another URL then navigation to page B will fail in Firefox with the following error:

1) [firefox] › bug.spec.js:3:1 › goto should not fail with the "NS_BINDING_ABORTED" error ========

  page.goto: NS_BINDING_ABORTED; maybe frame was detached?
  =========================== logs ===========================
  navigating to "http://localhost:3000/b", waiting until "load"
  ============================================================

    3 | test('goto should not fail with the "NS_BINDING_ABORTED" error', async ({ page }) => {
    4 |     await page.goto('http://localhost:3000/a');
  > 5 |     await page.goto('http://localhost:3000/b');
      |                ^
    6 | });
    7 |

See detailed logs here: https://github.com/wentwrong/pw-firefox-ns-binding-aborted/actions/runs/4124609214/jobs/7124068636

Currently there are no ways to workaround it except adding explicit page.waitForTimeout() after first navigation which is a little hacky and unreliable.

I expect that the page.goto API will work uniformly across all browsers and page-initiated navigation can't affect subsequent navigations done by page.goto. At least it shouldn't crash.

Related issues:

  • https://github.com/microsoft/playwright/issues/2061
  • https://github.com/microsoft/playwright/issues/13640
  • https://github.com/microsoft/playwright/issues/12912
  • https://github.com/microsoft/playwright/issues/5775
  • https://github.com/microsoft/playwright/issues/11677
  • https://github.com/microsoft/playwright/issues/8437
  • https://github.com/microsoft/playwright/discussions/14063

wentwrong avatar Feb 08 '23 14:02 wentwrong

I can reproduce, will assign it accordingly so we take a look for the next release. Thanks for your repro!

mxschmitt avatar Feb 08 '23 15:02 mxschmitt

Same issue. It works fine in non-Firefox browsers.

amitchaudhary140 avatar Feb 21 '23 06:02 amitchaudhary140

i confirm it happens with me too in google drive and most google sites i tried to use troubleshoot mode the same and it works on other browsers 108.0.2 (64-bit) Debian testing (bookworm) Linux 6.1.0-3-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.8-1 (2023-01-29) x86_64 GNU/Linux

minamfg avatar Mar 13 '23 18:03 minamfg

This behavior is consistent with what happens in Firefox when you type the url into the address bar while there is a concurrent navigation triggered by the page. I tweaked the example a little bit to make it more apparent:

const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));

require('http')
    .createServer((req, res) => {
        if (req.url === '/a') {
            res.writeHead(200, { 'content-type': 'text/html' });
            res.end(`
                <body>
                    <script>
                        setTimeout(() => {
                            window.location.pathname = '/c';
                        }, 1000);
                    </script>
                </body>
            `);
        } else if (req.url === '/b') {
            console.log('started b');
            sleep(1000).then(() => {
                res.writeHead(200, { 'content-type': 'text/html' });
                res.end(`BBBB`);
                console.log('finished b');
            });
        } else if (req.url === '/c') {
            console.log('started c');
            sleep(1000).then(() => {
                res.writeHead(200, { 'content-type': 'text/html' });
                res.end(`CCC`);
                console.log('finished c');
            });
        } else res.destroy();
    })
    .listen(3000, () => console.log('http://localhost:3000'));

If you type http://localhost:3000/b so that the server output is this:

started b
started c
finished b
finished c

Then navigation to c will succeed (same in Safari). If you change the server to respond to b almost immediately, so that the output is:

started c
started b
finished b
finished c

Then navigation b wins. If the order is this:

started c
started b
finished c
finished b

then navigation b wins. With the response order as in the latter two examples the test passes, with the first example it will fail as navigation to c wins and that is consistent with human interaction with Firefox.

yury-s avatar Mar 13 '23 20:03 yury-s

It's happening while opening google drive not my own server so i don't know if it's a bug or it this something from google to promote google chrome like they do with youtube and google image search i am not sure , i don't mind providing you with any logs or troubleshooting steps required to do from my end

On Mon, 13 Mar 2023, 22:54 Yury Semikhatsky, @.***> wrote:

This behavior is consistent with what happens in Firefox when you type the url into the address bar while there is a concurrent navigation triggered by the page. I tweaked the example a little bit to make it more apparent:

const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time)); require('http') .createServer((req, res) => { if (req.url === '/a') { res.writeHead(200, { 'content-type': 'text/html' }); res.end( <body> <script> setTimeout(() => { window.location.pathname = '/c'; }, 1000); </script> </body> ); } else if (req.url === '/b') { console.log('started b'); sleep(1000).then(() => { res.writeHead(200, { 'content-type': 'text/html' }); res.end(BBBB); console.log('finished b'); }); } else if (req.url === '/c') { console.log('started c'); sleep(1000).then(() => { res.writeHead(200, { 'content-type': 'text/html' }); res.end(CCC); console.log('finished c'); }); } else res.destroy(); }) .listen(3000, () => console.log('http://localhost:3000'));

If you type http://localhost:3000/b so that the server output is this:

started b started c finished b finished c

Then navigation to c will succeed (same in Safari). If you change the server to respond to b almost immediately, so that the output is:

started c started b finished b finished c

Then navigation b wins. If the order is this:

started c started b finished c finished b

then navigation b wins. With the response order as in the latter two examples the test passes, with the first example it will fail as navigation to c wins and that is consistent with human interaction with Firefox.

— Reply to this email directly, view it on GitHub https://github.com/microsoft/playwright/issues/20749#issuecomment-1466941886, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAOP4SE4EZBDZ7PRPOHZGXDW36CPVANCNFSM6AAAAAAUVKAKZM . You are receiving this because you commented.Message ID: @.***>

minamfg avatar Mar 13 '23 21:03 minamfg

It's happening while opening google drive not my own server so i don't know if it's a bug or it this something from google to promote google chrome like they do with youtube and google image search i am not sure , i don't mind providing you with any logs or troubleshooting steps required to do from my end

This seems to be different than calling page.goto() when the page is doing js redirect. Please file a separate issue with detailed reproduction steps.

yury-s avatar Mar 13 '23 22:03 yury-s

This behavior is consistent with what happens in Firefox when you type the url into the address bar while there is a concurrent navigation triggered by the page.

I understand that, but the problem is that there is no way to supress this error, and seeing it doesn't provide any useful information for the user.

For now we are experimenting with the following approach:

const test = base.extend({
    page: async ({ page, browserName }, use) => {
        const originalGoto = page.goto.bind(page);

        page.goto = async function(url, options) {
            if (!['firefox', 'webkit'].includes(browserName)) return originalGoto(url, options);

            const response = await originalGoto(url, options);
            const waitForURL = options?.waitForURL;

            if (waitForURL) await page.waitForURL(waitForURL);

            return response;
        };

        await use(page);
    }
});

test('prevents NS_BINDING_ABORTED error', async ({ page }) => {
    await page.goto('http://localhost:3000/a', { waitForURL: 'http://localhost:3000/b' });
    await page.goto('http://localhost:3000/b');
});

It's certainly better than adding explicit page.waitForTimeout()-s in every test, but it still doesn't feel like a proper way of handling this issue. First of all, we need to know in advance on which page the redirect chain will end up on, so that we can wait until this page is open to be sure that the navigation requests will not be canceled by the subsequent page.goto() invocations. And secondly, it slows down tests in Firefox and Webkit browsers.

With the help of the page.on('requestfailed') event handler we can catch this error, but unfortunately there is no way to tell Playwright to suppress it, although most users who encountered this error would like to be able to.

I'be really glad to hear on how this error is supposed to be solved or worked around, because as I stated in the issue message, as a user of Playwright framework I expect that the page.goto() API will work uniformly across all browsers. And even if opening a new page in a browser leads to cancellation of previous navigations, it should not fail the test whatsoever because it's not a sensible default behaviour.

wentwrong avatar Mar 24 '23 14:03 wentwrong

I'be really glad to hear on how this error is supposed to be solved or worked around, because as I stated in the issue message, as a user of Playwright framework I expect that the page.goto() API will work uniformly across all browsers.

The behavior varies between browsers in this scenario and playwright reflects that. You can wait for the redirect to finish before starting next navigation:

test('prevents NS_BINDING_ABORTED error', async ({ page, browserName }) => {
    await page.goto('http://localhost:3000/a');
    if (browserName !== 'chromium')
      await page.waitForURL('http://localhost:3000/b');
    await page.goto('http://localhost:3000/b');
});

alternatively you can start the new navigation in a new page object.

yury-s avatar Mar 24 '23 19:03 yury-s

The behavior varies between browsers in this scenario and playwright reflects that. You can wait for the redirect to finish before starting next navigation:

test('prevents NS_BINDING_ABORTED error', async ({ page, browserName }) => {
    await page.goto('http://localhost:3000/a');
    if (browserName !== 'chromium')
      await page.waitForURL('http://localhost:3000/b');
    await page.goto('http://localhost:3000/b');
});

I tried this and still Firefox keeps throwing the NS_BINDING_ABORTED error.

It doesn't happen if I wait for a 400ms timeout though.

Can this issue be reopened?

GermanJablo avatar Oct 25 '23 20:10 GermanJablo

confirmed this is still an issue in firefox

TheGreatTrazire avatar Oct 29 '23 09:10 TheGreatTrazire

Having this error when trying to load any video on YouTube, can only play them by going directly from menu to the video, trying to load the page via inserting the link doesn't load the page.

PedroVIOliv avatar Oct 30 '23 11:10 PedroVIOliv

fwiw, i'm using Playwright Test and was able to workaround with the expect + timeout

await expect( page ).toHaveURL( 'url', { timeout: 30000 } )

an example of the code that throws the error

await page.goto( 'url1' )
await page.getByRole( 'button', { name: 'Login' } ).click()
await page.waitForURL( 'url2' )

There are multiple redirects before getting to the URL in the page.waitForURL

This only happens in firefox. Chromium/WebKit work

Hope this helps someone else and/or the issue is reopened

Cheers! 🍻

mlalpho avatar Dec 07 '23 15:12 mlalpho

Still occurs for me on Firefox browser.

kosteklvp avatar Feb 05 '24 14:02 kosteklvp

I still see that ERROR. Can you please reopen the ticket?

aleksand88 avatar Feb 06 '24 16:02 aleksand88

This still exists in 1.41.2

jmanlu02 avatar Feb 29 '24 03:02 jmanlu02

Same here, still reproducible

NikkTod avatar Mar 11 '24 19:03 NikkTod

Any update on this issue?

alexdeathway avatar Mar 16 '24 13:03 alexdeathway

Maintainers probably do not review closed Issues. I would say we need to open a new one.

GermanJablo avatar Mar 16 '24 15:03 GermanJablo

Not sure if it helps, but I was able to get around this issue by opening a new tab and executing the goto there. const new_tab = await page.context().newPage(); await new_tab.goto(url)

fabianomobono avatar May 08 '24 21:05 fabianomobono

Is there any resolution on this issue? Still seeing this error in Firefox Error: page.goto: NS_BINDING_ABORTED; maybe frame was detached?

asombaty avatar May 16 '24 16:05 asombaty

Any news about this issue? It is still reproducible.

kosteklvp avatar Jul 17 '24 05:07 kosteklvp

Still getting this issue. Why is this issue closed @dgozman @pavelfeldman?

AshConnolly avatar Jul 31 '24 14:07 AshConnolly

Same problem here in I still see that ERROR. Can you please reopen the ticket?

I using "@playwright/test": "1.45.3",

renanpalmeira avatar Aug 05 '24 16:08 renanpalmeira

@mxschmitt Can this issue be reopened? Reported by multiple users, that it still occurs.

kosteklvp avatar Oct 21 '24 12:10 kosteklvp

UP

yozi-developer avatar Nov 06 '24 16:11 yozi-developer

halp

S33G avatar Nov 07 '24 21:11 S33G

Why is this closed?

S33G avatar Nov 18 '24 08:11 S33G

Fix problems please. NS_BINDING_ABORTED. Firefox has an error when downloading and playing Youtube videos. Everything is normal in Chrome. This error started occurring 8-12 months ago

Js8Uq0Iqu avatar Nov 18 '24 19:11 Js8Uq0Iqu

I have these troubles in Outlook OWA client, too.

alfsch avatar Dec 02 '24 08:12 alfsch

I've also started running into this issue and would like to see it re-opened.

alexkaufman06 avatar Jan 09 '25 22:01 alexkaufman06