[GH-ISSUE #3370] Callback Functions gives errors when using Captcha #9582

Closed
opened 2026-04-13 05:06:47 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @SooditK on GitHub (Jul 14, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/3370

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Create a simple nextjs application (or use a better auth template or something)
  2. Add catpcha plugin (I am using Cloudflare Turnstile with @marsidev/react-turnstile)
  3. on the signIn function implementation, add the additional fetchOptions to add the turnstileToken
  4. the callback functions like onError, onSuccess and onRequest throw an error - Object literal may only specify known properties, and 'CALLBACK_FUNCTION_NAME' does not exist in type '{ headers: { 'x-captcha-response': string; 'x-captcha-user-remote-ip': string; }; }'.
Image
await authClient.signIn.email(
  {
    email,
    password,
    callbackURL: '/chat',
    fetchOptions: {
      headers: {
        'x-captcha-response': turnstileToken ?? '',
        'x-captcha-user-remote-ip': userIp ?? '',
      },
    },
  },
  {
    onError(context) {
      setLoading(false);
      toast.error(context.error.message);
    },
    onSuccess() {
      setLoading(false);
      toast.success('Logged in successfully');
    },
    onRequest: () => {
      setLoading(true);
    },
  }
);

Current vs. Expected behavior

The callback function should've worked without throwing any type issues

What version of Better Auth are you using?

1.2.12

Provide environment information

OS: macOS 15.4 24E248 arm64
Host: Mac14,3
CPU: Apple M2

Which area(s) are affected? (Select all that apply)

Types

Auth config (if applicable)

export const auth = betterAuth({
  database: mongodbAdapter(db),
  plugins: [
    admin(),
    emailHarmony(),
    openAPI(),
    nextCookies(),
    captcha({
      provider: 'cloudflare-turnstile',
      secretKey: process.env.CLOUDFLARE_SECRET_KEY ?? '',
    }),
  ],
  emailAndPassword: {
    enabled: true,
  },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID ?? '',
      clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? '',
    },
  },
});

Additional context

No response

Originally created by @SooditK on GitHub (Jul 14, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/3370 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Create a simple nextjs application (or use a better auth template or something) 2. Add catpcha plugin (I am using Cloudflare Turnstile with `@marsidev/react-turnstile`) 3. on the `signIn` function implementation, add the additional `fetchOptions` to add the `turnstileToken` 4. the callback functions like `onError`, `onSuccess` and `onRequest` throw an error - `Object literal may only specify known properties, and 'CALLBACK_FUNCTION_NAME' does not exist in type '{ headers: { 'x-captcha-response': string; 'x-captcha-user-remote-ip': string; }; }'.` <img width="1029" height="138" alt="Image" src="https://github.com/user-attachments/assets/76f3755a-de18-44c3-a837-11a53d0d7244" /> ```ts await authClient.signIn.email( { email, password, callbackURL: '/chat', fetchOptions: { headers: { 'x-captcha-response': turnstileToken ?? '', 'x-captcha-user-remote-ip': userIp ?? '', }, }, }, { onError(context) { setLoading(false); toast.error(context.error.message); }, onSuccess() { setLoading(false); toast.success('Logged in successfully'); }, onRequest: () => { setLoading(true); }, } ); ``` ### Current vs. Expected behavior The callback function should've worked without throwing any type issues ### What version of Better Auth are you using? 1.2.12 ### Provide environment information ```bash OS: macOS 15.4 24E248 arm64 Host: Mac14,3 CPU: Apple M2 ``` ### Which area(s) are affected? (Select all that apply) Types ### Auth config (if applicable) ```typescript export const auth = betterAuth({ database: mongodbAdapter(db), plugins: [ admin(), emailHarmony(), openAPI(), nextCookies(), captcha({ provider: 'cloudflare-turnstile', secretKey: process.env.CLOUDFLARE_SECRET_KEY ?? '', }), ], emailAndPassword: { enabled: true, }, socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID ?? '', clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? '', }, }, }); ``` ### Additional context _No response_
GiteaMirror added the locked label 2026-04-13 05:06:47 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Jul 14, 2025):

The type error happens because the Better Auth client’s type definitions for signIn only accept specific options (like fetchOptions), and do not support callback functions such as onError, onSuccess, or onRequest in the argument object. TypeScript enforces this strictly, so passing those callbacks results in the error you’re seeing. This is a design limitation in the current version of Better Auth and not related to your captcha integration or fetchOptions usage see type definition.

To handle side effects (like showing toasts or setting loading state), use Promise chaining instead:

setLoading(true);
authClient.signIn.email({
  email,
  password,
  callbackURL: '/chat',
  fetchOptions: {
    headers: {
      'x-captcha-response': turnstileToken ?? '',
      'x-captcha-user-remote-ip': userIp ?? '',
    },
  },
})
  .then(() => {
    setLoading(false);
    toast.success('Logged in successfully');
  })
  .catch((err) => {
    setLoading(false);
    toast.error(err?.message || 'Sign in failed');
  });

There’s no official way to extend the types to allow those callbacks directly. If you want to keep a similar API, you could write your own wrapper function that calls signIn and invokes your callbacks as needed.

To reply, just mention @dosu.


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

<!-- gh-comment-id:3068024540 --> @dosubot[bot] commented on GitHub (Jul 14, 2025): <!-- Answer --> The type error happens because the Better Auth client’s type definitions for signIn only accept specific options (like fetchOptions), and do not support callback functions such as onError, onSuccess, or onRequest in the argument object. TypeScript enforces this strictly, so passing those callbacks results in the error you’re seeing. This is a design limitation in the current version of Better Auth and not related to your captcha integration or fetchOptions usage [see type definition](https://github.com/better-auth/better-auth/blob/7835167b8278c88dccbdfdf49ed987efe2811afd/packages/better-auth/src/client/types.ts). To handle side effects (like showing toasts or setting loading state), use Promise chaining instead: ```ts setLoading(true); authClient.signIn.email({ email, password, callbackURL: '/chat', fetchOptions: { headers: { 'x-captcha-response': turnstileToken ?? '', 'x-captcha-user-remote-ip': userIp ?? '', }, }, }) .then(() => { setLoading(false); toast.success('Logged in successfully'); }) .catch((err) => { setLoading(false); toast.error(err?.message || 'Sign in failed'); }); ``` There’s no official way to extend the types to allow those callbacks directly. If you want to keep a similar API, you could write your own wrapper function that calls signIn and invokes your callbacks as needed. <!-- 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/25c6dee0-4e97-4117-8744-e31017a50c2f?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/25c6dee0-4e97-4117-8744-e31017a50c2f?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/25c6dee0-4e97-4117-8744-e31017a50c2f?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/25c6dee0-4e97-4117-8744-e31017a50c2f?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/25c6dee0-4e97-4117-8744-e31017a50c2f?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/25c6dee0-4e97-4117-8744-e31017a50c2f?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/25c6dee0-4e97-4117-8744-e31017a50c2f?feedback_type=other)</sup>&nbsp;&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/3370)
Author
Owner

@frectonz commented on GitHub (Aug 11, 2025):

You don't have to set the fetch options, you can pass in the headers like in the following.

await authClient.signIn.email(
  {
    email: "",
    password: "",
    callbackURL: '/chat',
  },
  {
    headers: {
    },
    onError() {
    },
    onSuccess() {
    },
    onRequest() {
    },
  }
);
<!-- gh-comment-id:3175965140 --> @frectonz commented on GitHub (Aug 11, 2025): You don't have to set the fetch options, you can pass in the headers like in the following. ```typescript await authClient.signIn.email( { email: "", password: "", callbackURL: '/chat', }, { headers: { }, onError() { }, onSuccess() { }, onRequest() { }, } ); ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#9582