sindresorhus / got

🌐 Human-friendly and powerful HTTP request library for Node.js
MIT License
14.27k stars 935 forks source link

RequestError: read ECONNRESET #1843

Closed iim-ayush closed 3 years ago

iim-ayush commented 3 years ago

Describe the bug

I use Got stream as a way to play music songs in discord.js bot. Whenever I do that, after 2 minutes, the connections gets disconnected and I get this Error RequestError: read ECONNRESET

Actual behavior

Gives error : RequestError: read ECONNRESET

Expected behavior

It should have played all song completely without any issues.

Code to reproduce

got.stream(final.url, {
        retry : 5,
        headers: {
            'Connection': 'keep-alive',
            'Accept-Encoding': '',
            'Accept-Language': 'en-US,en;q=0.8'
        }
    })

Full ERROR, here :

  resource: <ref *3> AudioResource {
    playbackDuration: 134220,
    started: true,
    silenceRemaining: -1,
    edges: [
      <ref *1> {
        type: 'webm/opus demuxer',
        to: Node { edges: [ [Object] ], type: 'opus' },
        cost: 1,
        transformer: [Function: transformer],
        from: Node {
          edges: [ [Circular *1], [Object], [Object] ],
          type: 'webm/opus'
        }
      }
    ],
    playStream: WebmDemuxer {
      _readableState: ReadableState {
        objectMode: true,
        highWaterMark: 16,
        buffer: BufferList {
          head: { data: [Buffer [Uint8Array]], next: [Object] },
          tail: { data: [Buffer [Uint8Array]], next: null },
          length: 154
        },
        length: 154,
        pipes: [],
        flowing: null,
        ended: false,
        endEmitted: false,
        reading: false,
        constructed: true,
        sync: false,
        needReadable: false,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: false,
        errorEmitted: true,
        emitClose: true,
        autoDestroy: true,
        destroyed: true,
        errored: RequestError: read ECONNRESET
            at ClientRequest.<anonymous> (C:\Users\**SOME PATH**\aio-discord-bot\main\node_modules\got\dist\source\core\index.js:956:111)
            at Object.onceWrapper (node:events:514:26)
            at ClientRequest.emit (node:events:406:35)
            at ClientRequest.origin.emit (C:\Users\**SOME PATH**\aio-discord-bot\main\node_modules\@szmarczak\http-timer\dist\source\index.js:43:20)
            at TLSSocket.socketErrorListener (node:_http_client:447:9)
            at TLSSocket.emit (node:events:394:28)
            at emitErrorNT (node:internal/streams/destroy:157:8)
            at emitErrorCloseNT (node:internal/streams/destroy:122:3)
            at processTicksAndRejections (node:internal/process/task_queues:83:21)
            at TLSWrap.onStreamRead (node:internal/stream_base_commons:211:20) {
          code: 'ECONNRESET',
          timings: {
            start: 1629183240852,
            socket: 1629183240852,
            lookup: 1629183240852,
            connect: 1629183240868,
            secureConnect: 1629183240889,
            upload: 1629183240889,
            response: 1629183240924,
            end: undefined,
            error: 1629183376211,
            abort: 1629183376211,
            phases: [Object]
          }
        },
        closed: true,
        closeEmitted: false,
        defaultEncoding: 'utf8',
        awaitDrainWriters: null,
        multiAwaitDrain: false,
        readingMore: false,
        decoder: null,
        encoding: null,
        [Symbol(kPaused)]: null
      },
      _events: [Object: null prototype] {
        prefinish: [Function: prefinish],
        close: [ [Function (anonymous)], [Function: onclose] ],
        end: [Function: onend],
        finish: [Function: onfinish],
        error: [Function: onerror]
      },
      _eventsCount: 5,
      _maxListeners: undefined,
      _writableState: WritableState {
        objectMode: false,
        highWaterMark: 16384,
        finalCalled: false,
        needDrain: true,
        ending: false,
        ended: false,
        finished: false,
        destroyed: true,
        decodeStrings: true,
        defaultEncoding: 'utf8',
        length: 16384,
        writing: true,
        corked: 0,
        sync: false,
        bufferProcessing: false,
        onwrite: [Function: bound onwrite],
        writecb: [Function: nop],
        writelen: 16384,
        afterWriteTickInfo: null,
        buffered: [],
        bufferedIndex: 0,
        allBuffers: true,
        allNoop: true,
        pendingcb: 1,
        constructed: true,
        prefinished: false,
        errorEmitted: true,
        emitClose: true,
        autoDestroy: true,
        errored: RequestError: read ECONNRESET
            at ClientRequest.<anonymous> (C:\Users\**SOME PATH**\aio-discord-bot\main\node_modules\got\dist\source\core\index.js:956:111)
            at Object.onceWrapper (node:events:514:26)
            at ClientRequest.emit (node:events:406:35)
            at ClientRequest.origin.emit (C:\Users\**SOME PATH**\aio-discord-bot\main\node_modules\@szmarczak\http-timer\dist\source\index.js:43:20)
            at TLSSocket.socketErrorListener (node:_http_client:447:9)
            at TLSSocket.emit (node:events:394:28)
            at emitErrorNT (node:internal/streams/destroy:157:8)
            at emitErrorCloseNT (node:internal/streams/destroy:122:3)
            at processTicksAndRejections (node:internal/process/task_queues:83:21)
            at TLSWrap.onStreamRead (node:internal/stream_base_commons:211:20) {
          code: 'ECONNRESET',
          timings: {
            start: 1629183240852,
            socket: 1629183240852,
            lookup: 1629183240852,
            connect: 1629183240868,
            secureConnect: 1629183240889,
            upload: 1629183240889,
            response: 1629183240924,
            end: undefined,
            error: 1629183376211,
            abort: 1629183376211,
            phases: [Object]
          }
        },
        closed: true,
        closeEmitted: false,
        [Symbol(kOnFinished)]: []
      },
      allowHalfOpen: true,
      _remainder: null,
      _length: 851968,
      _count: 851859,
      _skipUntil: null,
      _track: { number: 1, type: 2 },
      _incompleteTrack: {},
      _ebmlFound: true,
      [Symbol(kCapture)]: false,
      [Symbol(kCallback)]: [Function: bound onwrite]
    },
    metadata: null,
    silencePaddingFrames: 5,
    audioPlayer: <ref *2> AudioPlayer {
      _events: [Object: null prototype] {},
      _eventsCount: 0,
      _maxListeners: undefined,
      subscribers: [
        PlayerSubscription {
          connection: VoiceConnection {
            _events: [Object: null prototype] {},
            _eventsCount: 0,
            _maxListeners: undefined,
            debug: null,
            rejoinAttempts: 0,
            onNetworkingClose: [Function: bound onNetworkingClose],
            onNetworkingStateChange: [Function: bound onNetworkingStateChange],
            onNetworkingError: [Function: bound onNetworkingError],
            onNetworkingDebug: [Function: bound onNetworkingDebug],
            _state: [Object],
            packets: [Object],
            joinConfig: [Object],
            [Symbol(kCapture)]: false
          },
          player: [Circular *2]
        }
      ],
      _state: {
        status: 'playing',
        playbackDuration: 134220,
        resource: [Circular *3],
        onStreamError: [Function: onStreamError]
      },
      behaviors: { noSubscriber: 'play', maxMissedFrames: 5 },
      debug: [Function (anonymous)],
      [Symbol(kCapture)]: false
    }
  }
}

Checklist

iim-ayush commented 3 years ago

Sorry, I thought it got fixed but no it still persists.

szmarczak commented 3 years ago

This is not a Got bug. Please provide an actual valid code to reproduce the issue.

iim-ayush commented 3 years ago

This is not a Got bug. Please provide an actual valid code to reproduce the issue.

        const connection = joinVoiceChannel({
            channelId : message.member.voice.channel.id,
            guildId : message.guild.id,
            adapterCreator: message.guild.voiceAdapterCreator
        })
        let info = await youtube.video_info('https://www.youtube.com/watch?v=P_NA6Hc8bf8')
        console.log(info.format[info.format.length - 1].url)
        let data = await got.stream(info.format[info.format.length - 1].url, {
            retry : 5,
            headers: {
                'Connection': 'keep-alive',
                'Accept-Encoding': '',
                'Accept-Language': 'en-US,en;q=0.8'
            }
        })

        let resource = createAudioResource(data, {
            inputType : StreamType.WebmOpus
        })
        let player = createAudioPlayer({
            behaviors: {
                noSubscriber: NoSubscriberBehavior.Play
            }
        })
        player.play(resource)

        connection.subscribe(player)

It shuts the connection down even if I mention to keep connection alive

URL that got plays :

https://r4---sn-gwpa-3o0l.googlevideo.com/videoplayback?expire=1629210019&ei=Q3EbYfLJNaSFjuMPh8eLgAQ&ip=**SOME IP **&id=o-APvdQ3oGhibkCZIy0mExKelMjPJ1lgEYBADM6fWtBWie&itag=251&source=youtube&requiressl=yes&mh=gP&mm=31%2C29&mn=sn-gwpa-3o0l%2Csn-qxa7snel&ms=au%2Crdu&mv=m&mvi=4&pl=22&initcwndbps=215000&vprv=1&mime=audio%2Fwebm&ns=T-t6t51n5PD4Ycj1HXrzgVwG&gir=yes&clen=109272459&dur=6716.681&lmt=1567799404957866&mt=1629188199&fvip=4&keepalive=yes&fexp=24001373%2C24007246&c=WEB&txp=5431432&n=T2TnyqaRYlwic0Qdnyi&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&sig=AOq0QJ8wRAIgexsI0AyhPUkVPPzh99wM5qSJ7hlHjrmPRIIzEYCgQcECIGbza-2NRlcRCjBt0_BnVSeeG1Cv3B0ycuMRKcdPsbtU&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIhAOwldmA9Q8gOcfF_5CC6phn72t3HY8GtfacjzV_C_wYKAiBbVYSAYQKEvK4ciV48SxU2He5Hgwn3D-2RJJ1xg_dKgg%3D%3D
szmarczak commented 3 years ago

It shuts the connection down even if I mention to keep connection alive

You don't keep the connection alive, you just send a keep-alive header. Pass an appropriate Agent instance.

szmarczak commented 3 years ago

URL that got plays :

Can you provide an URL that isn't exclusive? Where do you define youtube? I don't have youtube defined so can't run your code.

iim-ayush commented 3 years ago

It shuts the connection down even if I mention to keep connection alive

You don't keep the connection alive, you just send a keep-alive header. Pass an appropriate Agent instance.

Maybe this might help me, let me check

I will give you youtube variable once I finish this testing

iim-ayush commented 3 years ago

Ok So apparently, the server tends to close the connection

szmarczak commented 3 years ago

Next time please make sure what you're reporting is really a bug, thanks :)

iim-ayush commented 3 years ago

@szmarczak But this thing only happens when I run code in Linux not in Windows.

After adding Agent also.

szmarczak commented 3 years ago

this thing only happens when I run code in Linux not in Windows.

Can you repost the code please? I can have a look then.

iim-ayush commented 3 years ago

Can you repost the code please? I can have a look then.

const youtube = require('play-dl')
const agent = require('agentkeepalive')

         const connection = joinVoiceChannel({
            channelId : message.member.voice.channel.id,
            guildId : message.guild.id,
            adapterCreator: message.guild.voiceAdapterCreator
        })
        let info = await youtube.video_info('https://www.youtube.com/watch?v=DS-raAyMxl4')
        let data = await got.stream(info.format[info.format.length - 1].url, {
        retry : 5,
        headers: {
            'Connection': 'keep-alive',
            'Accept-Encoding': '',
            'Accept-Language': 'en-US,en;q=0.8',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
        },
        agent : {
            https : new agent.HttpsAgent()
        },
        http2 : true
    })

        let resource = createAudioResource(data, {
            inputType : StreamType.WebmOpus
        })
        let player = createAudioPlayer({
            behaviors: {
                noSubscriber: NoSubscriberBehavior.Play
            }
        })
        player.play(resource)

        connection.subscribe(player)

Here you go

I have some issues in same youtube url that I have used above

iim-ayush commented 3 years ago

Same code gave me errors again in Linux not in Windows. :(

I think got never reconnect in Linux or it has some kind of issue.

Error.

I played 5 times in a row on windows but it never gives me above error.

And on Linux, it gave me error on first attempt.

szmarczak commented 3 years ago

I can't reproduce.

const {youtube} = require('play-dl');
const got = require('got');
const https = require('https');

(async () => {
    const info = await youtube.video_info('https://www.youtube.com/watch?v=DS-raAyMxl4')
    const stream = got.stream(info.format[info.format.length - 1].url, {
        headers: {
            'Accept-Language': 'en-US,en;q=0.8',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
        },
        agent: {
            https: new https.Agent({keepAlive: true})
        },
        http2: true
    });

    stream.on('downloadProgress', console.log);

    stream.resume();
    stream.once('end', () => {
       console.log('Successfully ended');
    });
})();

Unless you're able to provide a fully reproducible example, let's keep this issue closed.

iim-ayush commented 3 years ago

Unless you're able to provide a fully reproducible example, let's keep this issue closed.

Now you can reproduce same error like me.

I have modified your code according to working of discord.js AudioPlayer. (setInterval is set to 0.9 seconds) [setInterval is added as AudioPlayer tries to get resource at every 0.9 seconds on average]

So just creating a similar condition.

const { youtube } = require('play-dl');
const got = require('got');
const https = require('https');

(async () => {
    const info = await youtube.video_info('https://www.youtube.com/watch?v=DS-raAyMxl4')
    const stream = got.stream(info.format[info.format.length - 1].url, {
        headers: {
            'Accept-Language': 'en-US,en;q=0.8',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
        },
        agent: {
            https: new https.Agent({keepAlive: true})
        },
        http2: true
    });

    stream.on('downloadProgress', (m) => {
        console.log(m)
        stream.pause()
    });

    setInterval(() => {
        stream.resume()
    }, 9 * 100)

    stream.once('end', () => {
       console.log('Successfully ended');
    });
})();

I tried this on Windows, I got Successfully ended

While on Linux, I get

  code: 'ECONNRESET',
  timings: {
    start: 1629206588820,
    socket: 1629206588820,
    lookup: 1629206588820,
    connect: 1629206588820,
    secureConnect: 1629206588820,
    upload: 1629206588820,
    response: 1629206588827,
    end: undefined,
    error: 1629206771782,
    abort: 1629206771782,
    phases: {
      wait: 0,
      dns: 0,
      tcp: 0,
      tls: 0,
      request: 0,
      firstByte: 7,
      download: undefined,
      total: 182962
    }
  }
}

@szmarczak It is up to you now, whether you want to open this issue or not.

iim-ayush commented 3 years ago

Make sure to end code with ctrl+c as it loops forever.

szmarczak commented 3 years ago

Looks like you don't read the entire body and YT is forcibly closing the connection. Save the stream in a PassThrough.

szmarczak commented 3 years ago

Set the highWaterMark to something high, like 10MB.

szmarczak commented 3 years ago

While on Linux, I get

I'm on Linux as well and I just tried your example yet again and I can't reproduce.

iim-ayush commented 3 years ago

Looks like you don't read the entire body and YT is forcibly closing the connection. Save the stream in a PassThrough.

Looks like a good idea 👍

Thanks for support

BTW got is very good library among all http libraries. I love it. ❤️

aminroosta commented 2 years ago

If anyone else ends up here, adding 'Accept-Encoding':'' to the headers fixed the issue for me.

{
  json: { /* your payload */ },
  headers: {
     'Accept-Encoding': '',
  }
}