[GH-ISSUE #7805] i18n: callback strategy never works because of missing request field #19543

Closed
opened 2026-04-15 18:47:04 -05:00 by GiteaMirror · 6 comments
Owner

Originally created by @mifopen on GitHub (Feb 5, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/7805

Originally assigned to: @bytaesu on GitHub.

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

I'm not sure if there are any specifics in my case as setup looks very basic.
I try to add an organization member that is already exists and the error message is never translated.

Current vs. Expected behavior

It should be translated

What version of Better Auth are you using?

1.5.0-beta.11

System info

-

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

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  i18n({
                translations: {
                    "de": {...},
                },
                detection: ["callback"],
                getLocale(request) {
                   // this function is never called because of the check for the missing request and the request is undefined on the context object.
                },
            }),
});

Additional context

Other fields seem ok. Like I can see headers, body, etc.

Originally created by @mifopen on GitHub (Feb 5, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/7805 Originally assigned to: @bytaesu on GitHub. ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce I'm not sure if there are any specifics in my case as setup looks very basic. I try to add an organization member that is already exists and the error message is never translated. ### Current vs. Expected behavior It should be translated ### What version of Better Auth are you using? 1.5.0-beta.11 ### System info ```bash - ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ i18n({ translations: { "de": {...}, }, detection: ["callback"], getLocale(request) { // this function is never called because of the check for the missing request and the request is undefined on the context object. }, }), }); ``` ### Additional context Other fields seem ok. Like I can see `headers`, `body`, etc.
GiteaMirror added the lockedbug labels 2026-04-15 18:47:04 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Feb 5, 2026):

It looks like the issue regarding the callback strategy not working due to a missing request field is related to how the request is being handled during the callback process. In your case, it seems the getLocale function isn't being called because the request context is not being properly received.

Here are some troubleshooting steps:

  1. Verify the Callback Handling: Ensure that your system's reverse proxies or middleware are not stripping necessary query parameters, such as request, which is crucial for the getLocale function to work. According to the documentation, issues commonly arise when parameters are stripped by reverse proxies or frameworks [2].

  2. Local Debugging: Utilize DevTools to inspect the callback request. Confirm whether the request is missing parameters and verify the handling of query and body parameters [5].

  3. Configuration Check: Double-check your callback URL configuration to make sure it aligns with what your authentication provider expects, including protocol and domain matching [5].

  4. Fallback Mechanism: In case no request parameters are present, consider implementing a fallback or default behavior in your code to handle these situations more gracefully.

If these steps don't resolve your issue, I recommend tagging Beka (@bekacru) or Max (@ping__) for further assistance. They would be more than happy to help!

Can you share more about how you are handling your callback configurations? That could help identify the issue better!

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3852109480 --> @better-auth-agent[bot] commented on GitHub (Feb 5, 2026): It looks like the issue regarding the callback strategy not working due to a missing request field is related to how the request is being handled during the callback process. In your case, it seems the `getLocale` function isn't being called because the request context is not being properly received. Here are some troubleshooting steps: 1. **Verify the Callback Handling**: Ensure that your system's reverse proxies or middleware are not stripping necessary query parameters, such as `request`, which is crucial for the `getLocale` function to work. According to the documentation, issues commonly arise when parameters are stripped by reverse proxies or frameworks [[2]](https://www.better-auth.com/docs/reference/errors/invalid_callback_request). 2. **Local Debugging**: Utilize DevTools to inspect the callback request. Confirm whether the request is missing parameters and verify the handling of query and body parameters [[5]](https://www.better-auth.com/docs/reference/errors/state_not_found). 3. **Configuration Check**: Double-check your callback URL configuration to make sure it aligns with what your authentication provider expects, including protocol and domain matching [[5]](https://www.better-auth.com/docs/reference/errors/state_not_found). 4. **Fallback Mechanism**: In case no request parameters are present, consider implementing a fallback or default behavior in your code to handle these situations more gracefully. If these steps don't resolve your issue, I recommend tagging Beka (@bekacru) or Max (@ping__) for further assistance. They would be more than happy to help! Can you share more about how you are handling your callback configurations? That could help identify the issue better! _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) • [Discord](https://discord.gg/better-auth) • [GitHub](https://github.com/better-auth/better-auth) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/better-auth) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/better-auth/better-auth)
Author
Owner

@dosubot[bot] commented on GitHub (Feb 5, 2026):

The i18n callback strategy isn't working because, in some backend flows (like adding an existing organization member), the request object is missing or undefined, so your getLocale callback never gets called. This is a known limitation and has been reported by others—it's often due to how the backend context is constructed or how certain API endpoints are invoked (for example, direct server-to-server calls may not provide a request object) [source].

For your specific case, untranslated error messages when adding an existing member are also a known bug. The error code returned (like USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL) is generated from the error message and not included in the official error codes, so translation keys are missing and the i18n plugin can't translate them [source].

Workarounds:

  • Use fallback detection strategies (like "header" or "cookie") in your i18n config to ensure at least some locale detection works when request is missing.
  • For error messages, you can manually map error codes to translations on the client side, or use the community package better-auth-localization for more robust localization [source].
  • Always check for undefined request in your callbacks and provide a sensible default locale [source].

This is a known gap and not something you can fully fix with configuration alone right now. If you want to track progress or see more details, check out the related issues and merged PRs:

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3852156193 --> @dosubot[bot] commented on GitHub (Feb 5, 2026): <!-- Answer --> The i18n callback strategy isn't working because, in some backend flows (like adding an existing organization member), the request object is missing or undefined, so your getLocale callback never gets called. This is a known limitation and has been reported by others—it's often due to how the backend context is constructed or how certain API endpoints are invoked (for example, direct server-to-server calls may not provide a request object) [[source](https://github.com/better-auth/better-auth/issues/6593)]. For your specific case, untranslated error messages when adding an existing member are also a known bug. The error code returned (like USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL) is generated from the error message and not included in the official error codes, so translation keys are missing and the i18n plugin can't translate them [[source](https://github.com/better-auth/better-auth/issues/4386)]. Workarounds: - Use fallback detection strategies (like "header" or "cookie") in your i18n config to ensure at least some locale detection works when request is missing. - For error messages, you can manually map error codes to translations on the client side, or use the community package better-auth-localization for more robust localization [[source](https://github.com/better-auth/better-auth/issues/1246#issuecomment-2646868290)]. - Always check for undefined request in your callbacks and provide a sensible default locale [[source](https://github.com/better-auth/better-auth/issues/7078)]. This is a known gap and not something you can fully fix with configuration alone right now. If you want to track progress or see more details, check out the related issues and merged PRs: - [i18n plugin docs and implementation](https://github.com/better-auth/better-auth/pull/7428) - [Error code translation bug](https://github.com/better-auth/better-auth/issues/4386) - [Missing request in backend hooks](https://github.com/better-auth/better-auth/issues/6593) <!-- 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/c2cbe81e-add1-4928-84e0-d57da353fdca?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/c2cbe81e-add1-4928-84e0-d57da353fdca?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/c2cbe81e-add1-4928-84e0-d57da353fdca?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/c2cbe81e-add1-4928-84e0-d57da353fdca?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/c2cbe81e-add1-4928-84e0-d57da353fdca?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/c2cbe81e-add1-4928-84e0-d57da353fdca?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/c2cbe81e-add1-4928-84e0-d57da353fdca?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=The%20i18n%20callback%20strategy%20isn%27t%20working%20because%2C%20in%20some%20backend%20flows%20%28like%20adding%20an%20existing%20organization%20member%29%2C%20the%20request%20object%20is%20missing%20or%20undefined%2C%20so%20your%20getLocale%20callback%20never%20gets%20called.%20This%20is%20a%20known%20limitation%20and%20has%20been%20reported%20by%20others%E2%80%94it%27s%20often%20due%20to%20how%20the%20backend%20context%20is%20constructed%20or%20how%20certain%20API%20endpoints%20are%20invoked%20%28for%20example%2C%20direct%20server-to-server%20calls%20may%20not%20provide%20a%20request%20object%29%20%5B%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/issues/6593%29%5D.%0A%0AFor%20your%20specific%20case%2C%20untranslated%20error%20messages%20when%20adding%20an%20existing%20member%20are%20also%20a%20known%20bug.%20The%20error%20code%20returned%20%28like%20USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL%29%20is%20generated%20from%20the%20error%20message%20and%20not%20included%20in%20the%20official%20error%20codes%2C%20so%20translation%20keys%20are%20missing%20and%20the%20i18n%20plugin%20can%27t%20translate%20them%20%5B%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/issues/4386%29%5D.%0A%0AWorkarounds%3A%20%0A-%20Use%20fallback%20detection%20strategies%20%28like%20%22header%22%20or%20%22cookie%22%29%20in%20your%20i18n%20config%20to%20ensure%20at%20least%20some%20locale%20detection%20works%20when%20request%20is%20missing.%0A-%20For%20error%20messages%2C%20you%20can%20manually%20map%20error%20codes%20to%20translations%20on%20the%20client%20side%2C%20or%20use%20the%20community%20package%20better-auth-localization%20for%20more%20robust%20localization%20%5B%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/issues/1246%23issuecomment-2646868290%29%5D.%0A-%20Always%20check%20for%20undefined%20request%20in%20your%20callbacks%20and%20provide%20a%20sensible%20default%20locale%20%5B%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/issues/7078%29%5D.%0A%0AThis%20is%20a%20known%20gap%20and%20not%20something%20you%20can%20fully%20fix%20with%20configuration%20alone%20right%20now.%20If%20you%20want%20to%20track%20progress%20or%20see%20more%20details%2C%20check%20out%20the%20related%20issues%20and%20merged%20PRs%3A%20%20%0A-%20%5Bi18n%20plugin%20docs%20and%20implementation%5D%28https%3A//github.com/better-auth/better-auth/pull/7428%29%20%20%0A-%20%5BError%20code%20translation%20bug%5D%28https%3A//github.com/better-auth/better-auth/issues/4386%29%20%20%0A-%20%5BMissing%20request%20in%20backend%20hooks%5D%28https%3A//github.com/better-auth/better-auth/issues/6593%29)&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/7805)
Author
Owner

@bytaesu commented on GitHub (Feb 6, 2026):

Hi @mifopen, I'll look into this today!

<!-- gh-comment-id:3858630698 --> @bytaesu commented on GitHub (Feb 6, 2026): Hi @mifopen, I'll look into this today!
Author
Owner

@bytaesu commented on GitHub (Feb 7, 2026):

Hi @mifopen,

I’ve opened a PR for this.

However, in this case, using a Header-Based Detection strategy may be more appropriate 🤔

<!-- gh-comment-id:3863215378 --> @bytaesu commented on GitHub (Feb 7, 2026): Hi @mifopen, I’ve opened a PR for this. However, in this case, using a Header-Based Detection strategy may be more appropriate 🤔
Author
Owner

@mifopen commented on GitHub (Feb 7, 2026):

Hmm, but why just not to pass the context?

  • there are other callbacks in the config where the context is always the last argument
  • yes, there is no 'request' in this case but only because all the examples in the docs (and also type definitions) only asks for 'headers'. It's weird than that I actually have all the information I need in the context (e.g. in 'headers') but can't access it because there is no 'request' field that is generally always optional because of this "universal" nature of the endpoints.

ps. we already have en established i18n machinery, so using the callback definitely makes more sense than using some helpers in the plugin (I'm talking about suggestion to use some other strategy). Moreover, I think that for the vast majority of users who are not just building new app but rather migrating an existing one, the callback strategy could be the only valid choice as locale detection is much more sophisticated than the included strategies.

<!-- gh-comment-id:3863889055 --> @mifopen commented on GitHub (Feb 7, 2026): Hmm, but why just not to pass the context? - there are other callbacks in the config where the context is always the last argument - yes, there is no 'request' in this case but only because all the examples in the docs (and also type definitions) only asks for 'headers'. It's weird than that I actually have all the information I need in the context (e.g. in 'headers') but can't access it because there is no 'request' field that is generally always optional because of this "universal" nature of the endpoints. ps. we already have en established i18n machinery, so using the callback definitely makes more sense than using some helpers in the plugin (I'm talking about suggestion to use some other strategy). Moreover, I think that for the vast majority of users who are not just building new app but rather migrating an existing one, the callback strategy could be the only valid choice as locale detection is much more sophisticated than the included strategies.
Author
Owner

@bytaesu commented on GitHub (Feb 8, 2026):

Hi @mifopen,

getLocale should be flexible for customization, so I agree with your point.

Since it's still in the beta version, we decided to make the change, even though it's a breaking one. Thanks for the feedback 🙏

<!-- gh-comment-id:3868336312 --> @bytaesu commented on GitHub (Feb 8, 2026): Hi @mifopen, `getLocale` should be flexible for customization, so I agree with your point. Since it's still in the beta version, we decided to make the change, even though it's a breaking one. Thanks for the feedback 🙏
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#19543