PLhery / node-twitter-api-v2

Strongly typed, full-featured, light, versatile yet powerful Twitter API v1.1 and v2 client for Node.js.
https://www.npmjs.com/package/twitter-api-v2
Apache License 2.0
1.29k stars 176 forks source link

[bug] ApiRequestError occurs often with `userClient.readOnly.v1.userTimeline` #358

Closed maximedupre closed 2 years ago

maximedupre commented 2 years ago

Describe the bug I use userClient.readOnly.v1.userTimeline the following way:

export async function fetchLast3200TweetsFromUser(
    userId: string,
    accessToken: string,
    accessSecret: string,
) {
    const userClient = createUserClient(accessToken, accessSecret);

    let userTimelineV1Paginator = await userClient.readOnly.v1.userTimeline(
        userId,
        { count: 200 },
    );

    userTimelineV1Paginator = await userTimelineV1Paginator.fetchLast(3000);

    return userTimelineV1Paginator.tweets;
}

This piece of code often throws an ApiRequestError. I am using a bunch of endpoints, but only v1.userTimeline has this issue. After further debugging (with the help of #353), I have been able to find the relevant error with console.log((e as any)._options.error), e being an ApiRequestError.

error: Error: read ECONNRESET
      at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
    errno: -104,
    code: 'ECONNRESET',
    syscall: 'read'
  }

For some, reason, at some point, the request connection is reset. Most of the time (always?), a bunch of the requests from the same paginator succeed before the failing request. E.g. in this screenshot, you can see only the last request fails

Xnapper-2022-08-31-10 41 08

This issue happens daily on my server, but not consistently (it doesn't happen every time the fetchLast3200TweetsFromUser method is called).

Thank you 😊🙏

Version

0xxMerkle commented 2 years ago

Hey, i'm getting the same error with searchStream endpoint (GET /2/tweets/search/stream ) From what i understand twitter api is closing the tcp connection abruptly... in my case the autoReconnect module starts the reconnection cycle then another error shows up telling that the stream is currently at the maximum allowed connection limit, which is not the case... i suspect that the stream is not closed properly before trying to reconnect

Twitter has a keep-alive packet.
Connection error! Error: read ECONNRESET
at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
    errno: -104,
    code: 'ECONNRESET',
    syscall: 'read'
}
{
    type: 'connection error',
    error: Error: read ECONNRESET
    {
    errno: -104,
    code: 'ECONNRESET',
    syscall: 'read'
    },
    message: 'Connection lost or closed by Twitter.'
}
Twitter ReconnectAttempt!
{
    type: 'reconnect error',
    error: ApiResponseError: Request failed with code 429
    at RequestHandlerHelper.createResponseError (/app/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.js:99:16)
    at RequestHandlerHelper.onResponseEndHandler (/app/node_modules/twitter-api-v2/dist/client-mixins/request-handler.helper.js:248:25)
    at Gunzip.emit (node:events:513:28)
    at Gunzip.emit (node:domain:489:12)
    at endReadableNT (node:internal/streams/readable:1358:12)
    at processTicksAndRejections (node:internal/process/task_queues:83:21) {
        error: true,
        type: 'response',
        code: 429,
        headers: {
            date: 'Tue, 06 Sep 2022 09:43:17 UTC',
            'x-access-level': 'read',
            'x-rate-limit-limit': '3000',
            'x-rate-limit-reset': '1662458297',
            'content-disposition': 'attachment; filename=json.json',
            'x-content-type-options': 'nosniff',
            'x-rate-limit-remaining': '2999',
            'strict-transport-security': 'max-age=631138519',
            'x-response-time': '83',
            connection: 'close'
        },
        rateLimit: { limit: 3000, remaining: 2999, reset: 1662458297 },
        data: {
            title: 'ConnectionException',
            detail: 'This stream is currently at the maximum allowed connection limit.',
            connection_issue: 'TooManyConnections',
            type: 'https://api.twitter.com/2/problems/streaming-connection'
        }
    },
    message: 'Reconnect error - 1 attempts made yet.'
}
alkihis commented 2 years ago

@maximedupre I don't think the issue here is the library. ECONNRESET is throw by node itself (using its underlying wrapper for network OS-based syscalls), so unless do the request again, I don't know what we could do more.

@0xxMerkle, this issue is already reported since a long time, but it is hardly reproductible (on my side, I let a stream open for 1 month without any problem ; and triggering manual reconnection by disconnecting my computer make the reconnect process just fine), so I cannot help you with that. Consider testing it and make a PR if you have time to.