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

HTTP Keep-alive, "socket hang up" ECONNERR on a long-running second request #6113

Open
snarky-puppy opened this issue Dec 4, 2023 · 16 comments

Comments

@snarky-puppy
Copy link

snarky-puppy commented Dec 4, 2023

Describe the bug

On keep-alive connections, if a timeout value is given to the first request but not on subsequent requests, the subsequent requests will eventually throw a "socket hang up" error.

To Reproduce

const http = require('http');
const axios = require('axios');

describe('socket hang up', () => {
    let server;
    beforeAll(done => {
        server = http.createServer(async (req, res) => {
            if (req.url === '/wait') {
                await new Promise(resolve => setTimeout(resolve, 5000));
            }
            res.end('ok');
        });
        server.listen(3000, done);
    });

    afterAll(done => {
        server.close(done);
    });

    it('will fail with "socket hang up"', async () => {
        const baseURL = `http://localhost:3000`;
        await axios.get('/1', {baseURL, timeout: 1000});
        await axios.get(`/wait`, {baseURL, timeout: 0});
    }, 15000);
});

Code snippet

No response

Expected behavior

  1. "socket hang up" is misleading because it indicates the server closed the connection (in this bug the opposite is true)
  2. One would not expect that a timeout would keep running after a request has completed. This is a (quite major IMO) footgun.

Axios Version

0.22.0 - 1.6.2

Adapter Version

HTTP

Browser

No response

Browser Version

No response

Node.js Version

20.9.0

OS

OSX 14

Additional Library Versions

No response

Additional context/Screenshots

tcpdump
@avermeil
Copy link

avermeil commented Dec 6, 2023

We're also affected by this bug.

@Avariya
Copy link

Avariya commented Dec 8, 2023

Cheers! I am affected with same bug, but can only reproduce it at Node 20.10, fallback to Node 18.18 works fine.

@snarky-puppy
Copy link
Author

The cause of this issue is the way follow-redirects implements timeout. It has problems when dealing with keep-alive connections. A simple fix is to remove the timeout event handler when the request finishes, but I'm not sure this will work for all use-cases, as that library is mostly geared towards earlier node versions.

@NaZaRKIN123
Copy link

Same issue here. Is there any workaround except a dumb retry?

@snarky-puppy
Copy link
Author

snarky-puppy commented Jan 25, 2024

Same issue here. Is there any workaround except a dumb retry?

@NaZaRKIN123 Something like this would work:

axios.defaults.httpAgent = new Agent({ keepAlive: false });

@TkDodo
Copy link

TkDodo commented Jan 26, 2024

I can confirm that the workaround provided by @snarky-puppy worked for us 🙏

@chanyk-joseph
Copy link

chanyk-joseph commented May 8, 2024

Thanks for the detail investigation. The keepAlive is needed on my project in order to reduce latency
In case we disable follow-redirects, would that be solved?

@ricfio
Copy link

ricfio commented Jun 19, 2024

+1

@KyrieLii
Copy link

KyrieLii commented Jul 2, 2024

+1

2 similar comments
@davidln777
Copy link

+1

@dathacky
Copy link

+1

MattiasOlla added a commit to BonnierNews/lu-common that referenced this issue Jul 29, 2024
HTTP keepalive was enabled by default in Node 20, and is apparently causing errors for axios. See e.g. nodejs/node#47130, axios/axios#6113
@nikwen
Copy link

nikwen commented Aug 11, 2024

Cheers! I am affected with same bug, but can only reproduce it at Node 20.10, fallback to Node 18.18 works fine.

This is because of #6536. Short summary: Node.js changed its default Keep-Alive behavior after Node.js 18.

@tjx666
Copy link

tjx666 commented Sep 22, 2024

I try following code in next.js _app.tsx, but not worked:

// _app.tsx
if (typeof window === 'undefined') {
  /**
   * @see https://github.com/axios/axios/issues/6113#issuecomment-1909291937
   */
  async function fixAxiosKeepAlive() {
    const { default: axios } = await import('axios');
    const { Agent } = await import('https');
    axios.defaults.httpAgent = new Agent({ keepAlive: false });
  }
  fixAxiosKeepAlive();
}

Because of this issue, we have to revert from node 20 to 18, or we may try to remove the axios from our project.

@zuozp8
Copy link

zuozp8 commented Sep 23, 2024

axios.defaults.httpsAgent = new Agent({ keepAlive: false });

@tjx666 you should replace httpsAgent (and httpAgent too if you use http, but it's a different class)

@anchenyi
Copy link

+1

1 similar comment
@ExpliuM
Copy link

ExpliuM commented Oct 7, 2024

+1

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

No branches or pull requests