[GH-ISSUE #5514] How to deal with connectTimeoutError #18903

Closed
opened 2026-04-15 17:35:58 -05:00 by GiteaMirror · 7 comments
Owner

Originally created by @pptypeset on GitHub (Oct 23, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/5514

I can't access GitHub stably due to local network restrictions. So with
await authClient.signIn.social({provider: "github"}),
it reports error now and then

2025-10-23T02:37:58.762Z ERROR [Better Auth]:  TypeError: fetch failed
    at node:internal/deps/undici/undici:13510:13
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async betterFetch (file:///myproject/node_modules/.pnpm/@better-fetch+fetch@1.1.18/node_modules/@better-fetch/fetch/dist/index.js:546:18)
    at async validateAuthorizationCode (file:///myproject/node_modules/.pnpm/better-auth@1.3.27_@sveltejs+kit@2.46.4_@sveltejs+vite-plugin-svelte@6.2.1_svelte@5.39._8136a90adc4c84e62a5bc80e00c117d6/node_modules/better-auth/dist/shared/better-auth.C3-_8m-g.mjs:1123:27)
    at async file:///myproject/node_modules/.pnpm/better-auth@1.3.27_@sveltejs+kit@2.46.4_@sveltejs+vite-plugin-svelte@6.2.1_svelte@5.39._8136a90adc4c84e62a5bc80e00c117d6/node_modules/better-auth/dist/shared/better-auth.C3-_8m-g.mjs:4544:16
    at async internalHandler (file:///myproject/node_modules/.pnpm/better-call@1.0.19/node_modules/better-call/dist/index.js:676:22)
    at async api.<computed> (file:///myproject/node_modules/.pnpm/better-auth@1.3.27_@sveltejs+kit@2.46.4_@sveltejs+vite-plugin-svelte@6.2.1_svelte@5.39._8136a90adc4c84e62a5bc80e00c117d6/node_modules/better-auth/dist/shared/better-auth.C3-_8m-g.mjs:6688:22)
    at async processRequest (file:///myproject/node_modules/.pnpm/better-call@1.0.19/node_modules/better-call/dist/index.js:3152:24)
    at async handler (file:///myproject/node_modules/.pnpm/better-call@1.0.19/node_modules/better-call/dist/index.js:3188:19)
    at async fn (file:///myproject/node_modules/.pnpm/@sveltejs+kit@2.46.4_@sveltejs+vite-plugin-svelte@6.2.1_svelte@5.39.11_vite@7.1.9__svelte@5.39.11_vite@7.1.9/node_modules/@sveltejs/kit/src/exports/hooks/sequence.js:102:13) {
  [cause]: ConnectTimeoutError: Connect Timeout Error (attempted address: github.com:443, timeout: 10000ms)
      at onConnectTimeout (node:internal/deps/undici/undici:2602:28)
      at Immediate._onImmediate (node:internal/deps/undici/undici:2583:11)
      at process.processImmediate (node:internal/timers:483:21)
      at process.callbackTrampoline (node:internal/async_hooks:130:17) {
    code: 'UND_ERR_CONNECT_TIMEOUT'
  }
}

And the message Better Auth Error on the page doesnot help a lot to tell the user what is the real problem.
I want to customize the message or better retry signin automatically for this situation.
I tried await authClient.signIn.social({provider: "github"}).catch(...) but it does not catch the error at all.

Originally created by @pptypeset on GitHub (Oct 23, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/5514 I can't access GitHub stably due to local network restrictions. So with `await authClient.signIn.social({provider: "github"})`, it reports error now and then ``` 2025-10-23T02:37:58.762Z ERROR [Better Auth]: TypeError: fetch failed at node:internal/deps/undici/undici:13510:13 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async betterFetch (file:///myproject/node_modules/.pnpm/@better-fetch+fetch@1.1.18/node_modules/@better-fetch/fetch/dist/index.js:546:18) at async validateAuthorizationCode (file:///myproject/node_modules/.pnpm/better-auth@1.3.27_@sveltejs+kit@2.46.4_@sveltejs+vite-plugin-svelte@6.2.1_svelte@5.39._8136a90adc4c84e62a5bc80e00c117d6/node_modules/better-auth/dist/shared/better-auth.C3-_8m-g.mjs:1123:27) at async file:///myproject/node_modules/.pnpm/better-auth@1.3.27_@sveltejs+kit@2.46.4_@sveltejs+vite-plugin-svelte@6.2.1_svelte@5.39._8136a90adc4c84e62a5bc80e00c117d6/node_modules/better-auth/dist/shared/better-auth.C3-_8m-g.mjs:4544:16 at async internalHandler (file:///myproject/node_modules/.pnpm/better-call@1.0.19/node_modules/better-call/dist/index.js:676:22) at async api.<computed> (file:///myproject/node_modules/.pnpm/better-auth@1.3.27_@sveltejs+kit@2.46.4_@sveltejs+vite-plugin-svelte@6.2.1_svelte@5.39._8136a90adc4c84e62a5bc80e00c117d6/node_modules/better-auth/dist/shared/better-auth.C3-_8m-g.mjs:6688:22) at async processRequest (file:///myproject/node_modules/.pnpm/better-call@1.0.19/node_modules/better-call/dist/index.js:3152:24) at async handler (file:///myproject/node_modules/.pnpm/better-call@1.0.19/node_modules/better-call/dist/index.js:3188:19) at async fn (file:///myproject/node_modules/.pnpm/@sveltejs+kit@2.46.4_@sveltejs+vite-plugin-svelte@6.2.1_svelte@5.39.11_vite@7.1.9__svelte@5.39.11_vite@7.1.9/node_modules/@sveltejs/kit/src/exports/hooks/sequence.js:102:13) { [cause]: ConnectTimeoutError: Connect Timeout Error (attempted address: github.com:443, timeout: 10000ms) at onConnectTimeout (node:internal/deps/undici/undici:2602:28) at Immediate._onImmediate (node:internal/deps/undici/undici:2583:11) at process.processImmediate (node:internal/timers:483:21) at process.callbackTrampoline (node:internal/async_hooks:130:17) { code: 'UND_ERR_CONNECT_TIMEOUT' } } ``` And the message `Better Auth Error` on the page doesnot help a lot to tell the user what is the real problem. I want to customize the message or better retry signin automatically for this situation. I tried `await authClient.signIn.social({provider: "github"}).catch(...)` but it does not catch the error at all.
GiteaMirror added the locked label 2026-04-15 17:35:58 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Oct 23, 2025):

Hi @pptypeset! I'm Dosu and I’m helping the better-auth team.

The ConnectTimeoutError happens because Better Auth uses a default 10s timeout for network requests to GitHub, and unstable local networks can cause these requests to fail. The generic "Better Auth Error" message is shown because errors are handled internally and not exposed in a way that lets you customize the user-facing message or catch them with .catch() directly.

To customize error messages and enable retry logic, use the onError callback in the options for signIn.social. You can detect a ConnectTimeoutError by checking the error's code property (e.g., 'UND_ERR_CONNECT_TIMEOUT'). For example:

await authClient.signIn.social(
  { provider: "github" },
  {
    onError: (error) => {
      if (error?.cause?.code === "UND_ERR_CONNECT_TIMEOUT") {
        // Show a custom message or trigger a retry
        showToast("Network timeout. Please check your connection and try again.");
      } else {
        showToast("Sign-in failed: " + error.message);
      }
    },
    onSuccess: (result) => {
      // Handle success
    }
  }
);

If you want to use .catch() or try/catch, wrap the call in a new Promise and resolve/reject based on the callbacks:

function signInWithPromise(options) {
  return new Promise((resolve, reject) => {
    authClient.signIn.social(
      options,
      {
        onSuccess: resolve,
        onError: reject,
      }
    );
  });
}

// Usage:
signInWithPromise({ provider: "github" })
  .then((result) => { /* handle success */ })
  .catch((error) => {
    if (error?.cause?.code === "UND_ERR_CONNECT_TIMEOUT") {
      // Custom message or retry logic
    }
  });

For automatic retries, you can implement a simple retry loop in your wrapper function, or use Better Auth's underlying Better Fetch retry options by providing a custom fetch implementation via fetchOptions.customFetchImpl when creating the client. Note that network failures like ConnectTimeoutError do not trigger retries by default, so you need to handle retries manually in your code. See more details and examples in this thread.

References:

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

<!-- gh-comment-id:3434903772 --> @dosubot[bot] commented on GitHub (Oct 23, 2025): <!-- Greeting --> Hi @pptypeset! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> The ConnectTimeoutError happens because Better Auth uses a default 10s timeout for network requests to GitHub, and unstable local networks can cause these requests to fail. The generic "Better Auth Error" message is shown because errors are handled internally and not exposed in a way that lets you customize the user-facing message or catch them with `.catch()` directly. To customize error messages and enable retry logic, use the `onError` callback in the options for `signIn.social`. You can detect a ConnectTimeoutError by checking the error's `code` property (e.g., `'UND_ERR_CONNECT_TIMEOUT'`). For example: ```js await authClient.signIn.social( { provider: "github" }, { onError: (error) => { if (error?.cause?.code === "UND_ERR_CONNECT_TIMEOUT") { // Show a custom message or trigger a retry showToast("Network timeout. Please check your connection and try again."); } else { showToast("Sign-in failed: " + error.message); } }, onSuccess: (result) => { // Handle success } } ); ``` If you want to use `.catch()` or `try/catch`, wrap the call in a new Promise and resolve/reject based on the callbacks: ```js function signInWithPromise(options) { return new Promise((resolve, reject) => { authClient.signIn.social( options, { onSuccess: resolve, onError: reject, } ); }); } // Usage: signInWithPromise({ provider: "github" }) .then((result) => { /* handle success */ }) .catch((error) => { if (error?.cause?.code === "UND_ERR_CONNECT_TIMEOUT") { // Custom message or retry logic } }); ``` For automatic retries, you can implement a simple retry loop in your wrapper function, or use Better Auth's underlying Better Fetch retry options by providing a custom fetch implementation via `fetchOptions.customFetchImpl` when creating the client. Note that network failures like ConnectTimeoutError do not trigger retries by default, so you need to handle retries manually in your code. See more details and examples in [this thread](https://github.com/better-auth/better-auth/issues/987). References: - [Why .catch() doesn't work and how to wrap for promise rejection](https://github.com/better-auth/better-auth/issues/3443) - [Custom error handling and retry logic](https://github.com/better-auth/better-auth/issues/987) - [ConnectTimeoutError root cause and betterFetch config](https://github.com/better-auth/better-auth/issues/4537) <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/139abcb1-2bda-46e3-9559-42d480d5815e?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/139abcb1-2bda-46e3-9559-42d480d5815e?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/139abcb1-2bda-46e3-9559-42d480d5815e?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/139abcb1-2bda-46e3-9559-42d480d5815e?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/139abcb1-2bda-46e3-9559-42d480d5815e?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/139abcb1-2bda-46e3-9559-42d480d5815e?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/139abcb1-2bda-46e3-9559-42d480d5815e?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/5514)
Author
Owner

@pptypeset commented on GitHub (Oct 24, 2025):

I tried both methods with

onError: (error) => {
      debugger
      console.log(error)
    },

It does not pause at all when the ConnectTimeoutError happens.

<!-- gh-comment-id:3441381274 --> @pptypeset commented on GitHub (Oct 24, 2025): I tried both methods with ``` onError: (error) => { debugger console.log(error) }, ``` It does not pause at all when the `ConnectTimeoutError` happens.
Author
Owner

@dosubot[bot] commented on GitHub (Oct 24, 2025):

Your onError callback isn’t triggered for ConnectTimeoutError because, in the Better Auth social sign-in flow, network errors like this are caught and handled on the server side during the OAuth callback phase. Instead of surfacing the error to the client (and thus to your onError handler), the server logs the error and redirects to a generic error page or state, which is why you only see a generic "Better Auth Error" and your debugger/console.log never runs. This is a design choice in the Better Auth OAuth plugin: errors from the token exchange (including network failures) are not propagated back to the client-side callback—they’re handled internally and result in a redirect-on-error instead (see code).

Because of this, customizing the error message or implementing retry logic on the client side isn’t possible for these network errors. If you need more granular error handling or user feedback, you’d need to modify the server-side error handling in your own fork or request a feature to propagate these errors to the client.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

<!-- gh-comment-id:3441402963 --> @dosubot[bot] commented on GitHub (Oct 24, 2025): <!-- Answer --> Your onError callback isn’t triggered for ConnectTimeoutError because, in the Better Auth social sign-in flow, network errors like this are caught and handled on the server side during the OAuth callback phase. Instead of surfacing the error to the client (and thus to your onError handler), the server logs the error and redirects to a generic error page or state, which is why you only see a generic "Better Auth Error" and your debugger/console.log never runs. This is a design choice in the Better Auth OAuth plugin: errors from the token exchange (including network failures) are not propagated back to the client-side callback—they’re handled internally and result in a redirect-on-error instead [(see code)](https://github.com/better-auth/better-auth/blob/7641c0cf43d24812831ba2f933ad283c3f341489/packages/better-auth/src/plugins/generic-oauth/index.ts). Because of this, customizing the error message or implementing retry logic on the client side isn’t possible for these network errors. If you need more granular error handling or user feedback, you’d need to modify the server-side error handling in your own fork or request a feature to propagate these errors to the client. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/7a2d8ffd-735c-4f50-aa48-9a8c6a320acc?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/7a2d8ffd-735c-4f50-aa48-9a8c6a320acc?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/7a2d8ffd-735c-4f50-aa48-9a8c6a320acc?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/7a2d8ffd-735c-4f50-aa48-9a8c6a320acc?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/7a2d8ffd-735c-4f50-aa48-9a8c6a320acc?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/7a2d8ffd-735c-4f50-aa48-9a8c6a320acc?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/7a2d8ffd-735c-4f50-aa48-9a8c6a320acc?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/5514)
Author
Owner

@ping-maxwell commented on GitHub (Oct 24, 2025):

Hmm, yeah I've noticed a few areas in our social provider code which don't carry the error to the front-end. I've started work on a PR not too long ago but it's still in progress.
It's possible your fetch error is coming from a different source than the ones I'm trying to solve.. do you have any clues which specific URL it's trying to hit which gives this error?
(If not it's okay, I'll work on my PR still and then we can test if things work for you)

<!-- gh-comment-id:3441429577 --> @ping-maxwell commented on GitHub (Oct 24, 2025): Hmm, yeah I've noticed a few areas in our social provider code which don't carry the error to the front-end. I've started work on a PR not too long ago but it's still in progress. It's possible your fetch error is coming from a different source than the ones I'm trying to solve.. do you have any clues which specific URL it's trying to hit which gives this error? (If not it's okay, I'll work on my PR still and then we can test if things work for you)
Author
Owner

@ping-maxwell commented on GitHub (Oct 24, 2025):

PR in question: https://github.com/better-auth/better-auth/pull/5278

<!-- gh-comment-id:3441431441 --> @ping-maxwell commented on GitHub (Oct 24, 2025): PR in question: https://github.com/better-auth/better-auth/pull/5278
Author
Owner

@pptypeset commented on GitHub (Oct 27, 2025):

@ping-maxwell It happens when I try sign in with github via await authClient.signIn.social({provider: "github"}).
@dosu I would like to have some hook provided by better auth to capture and deal with the error at server-side rather than forking, if that is possible.

<!-- gh-comment-id:3449856147 --> @pptypeset commented on GitHub (Oct 27, 2025): @ping-maxwell It happens when I try sign in with github via `await authClient.signIn.social({provider: "github"})`. @dosu I would like to have some `hook` provided by better auth to capture and deal with the error at server-side rather than forking, if that is possible.
Author
Owner

@dosubot[bot] commented on GitHub (Oct 27, 2025):

Better Auth does not currently provide a server-side hook or extension point to capture and handle OAuth/network errors (like ConnectTimeoutError) during social sign-in. These errors are caught internally in the OAuth callback handler and result in a redirect to a generic error URL, without exposing a way for you to intercept or customize the handling server-side without forking the codebase. This is a known limitation, and while there is ongoing work to improve error logging and forwarding (see PR #5278), it does not introduce a server-side hook for custom error handling yet.

There are plugin hooks for endpoints like /sign-in/social that let you validate input or run logic before/after login requests, but these do not cover network errors during the OAuth token exchange phase—those happen later in the flow and are not exposed to these hooks. If you need to handle these errors specifically, you would need to wait for future extensibility or changes from the maintainers, as there is no supported workaround at this time.
Reference: code analysis

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

<!-- gh-comment-id:3449865728 --> @dosubot[bot] commented on GitHub (Oct 27, 2025): <!-- Answer --> Better Auth does not currently provide a server-side hook or extension point to capture and handle OAuth/network errors (like ConnectTimeoutError) during social sign-in. These errors are caught internally in the OAuth callback handler and result in a redirect to a generic error URL, without exposing a way for you to intercept or customize the handling server-side without forking the codebase. This is a known limitation, and while there is ongoing work to improve error logging and forwarding (see [PR #5278](https://github.com/better-auth/better-auth/pull/5278)), it does not introduce a server-side hook for custom error handling yet. There are plugin hooks for endpoints like `/sign-in/social` that let you validate input or run logic before/after login requests, but these do not cover network errors during the OAuth token exchange phase—those happen later in the flow and are not exposed to these hooks. If you need to handle these errors specifically, you would need to wait for future extensibility or changes from the maintainers, as there is no supported workaround at this time. [Reference: code analysis](https://github.com/better-auth/better-auth/blob/97cd4a205957002568915b2f8b85c2b9c8de76d9/packages/better-auth/src/plugins/generic-oauth/index.ts) <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/be962d14-8eb4-4756-8da5-d5800ad1b0fb?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/be962d14-8eb4-4756-8da5-d5800ad1b0fb?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/be962d14-8eb4-4756-8da5-d5800ad1b0fb?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/be962d14-8eb4-4756-8da5-d5800ad1b0fb?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/be962d14-8eb4-4756-8da5-d5800ad1b0fb?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/be962d14-8eb4-4756-8da5-d5800ad1b0fb?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/be962d14-8eb4-4756-8da5-d5800ad1b0fb?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/5514)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#18903