getSession (and customSession) don't include additionalFields EVEN on SERVER SIDE!.. contrary to inferred typing. #1670

Closed
opened 2026-03-13 08:54:56 -05:00 by GiteaMirror · 7 comments
Owner

Originally created by @najibghadri on GitHub (Aug 8, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

I've gone deep in docs, issues and testing and this "limitation" is absolutely unclear.
(I'm on latest 1.3.4) I've also opened this in discord: https://discord.com/channels/1288403910284935179/1403419135093903472

This isn't about using infers for types, that works well for both server and client side.

It seems like even though adding additionalFields, even with returned: true (which is documented as: If the value should be returned on a response body.) it isn't returned to the client when the client calls getSession...

So I found here and there that additionalFields is only for the server side (then what is the returned field for??) and they are all stripped from getSession to client for "safety reasons".. It seems like an unnecessary limitation to me.. (Ping answered here but this isn't clearly documented anywhere else https://www.answeroverflow.com/m/1374165269303263244)

Okay, then I go for customSession and I nuke the config a bit fine, then I see that the customSession already provides the user and the session from params, but still without the additional fields.

Why do I have to make two DB queries where the whole point of this additionalFields would be to avoid extra steps and roundtrips and neatly include the fields.. it already works for the server side why would you strip them away, and even in customSession? Then would it make a LOT more sense for customSession to not do any DB call and let us do that too?

I don't get this I feel like this should at least be easily configurable, like say with returned field in additionalFields or another field.

I'm doing this:

user: {
    additionalFields: {
      isAdmin: {
        type: "boolean",
        required: true,
        defaultValue: false,
        input: false, // Don't allow users to set this during signup
        returned: true,
      },
    },
  },

in the options object
Then using that object:

export const auth = betterAuth({
  ...authOptions,
  plugins: [
    ...(authOptions.plugins ?? []),
    customSession(async ({ user, session }) => {
      console.log("customSession", user, session);

    }, authOptions),
  ],
});

And the type of user indeed has isAdmin but the runtime doesn't....?

Current vs. Expected behavior

Have an additional prop for additionalFields : isPublic, which tells better-auth to return to getSession to client too.
Or at least include all additionalFields in customSession callback, to match the typing correctly, and already making a DB request..

What version of Better Auth are you using?

1.3.4

Provide environment information

-

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

Documentation, Client, Backend, Types

Auth config (if applicable)

- already included

Additional context

No response

Originally created by @najibghadri on GitHub (Aug 8, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce I've gone deep in docs, issues and testing and this "limitation" is absolutely unclear. (I'm on latest 1.3.4) I've also opened this in discord: https://discord.com/channels/1288403910284935179/1403419135093903472 This isn't about using infers for types, that works well for both server and client side. It seems like even though adding additionalFields, even with returned: true (which is documented as: If the value should be returned on a response body.) it isn't returned to the client when the client calls getSession... So I found here and there that additionalFields is only for the server side (then what is the returned field for??) and they are all stripped from getSession to client for "safety reasons".. It seems like an unnecessary limitation to me.. (Ping answered here but this isn't clearly documented anywhere else https://www.answeroverflow.com/m/1374165269303263244) Okay, then I go for customSession and I nuke the config a bit fine, then I see that the customSession already provides the user and the session from params, but still without the additional fields. Why do I have to make two DB queries where the whole point of this additionalFields would be to avoid extra steps and roundtrips and neatly include the fields.. it already works for the server side why would you strip them away, and even in customSession? Then would it make a LOT more sense for customSession to not do any DB call and let us do that too? I don't get this I feel like this should at least be easily configurable, like say with `returned` field in additionalFields or another field. I'm doing this: ``` user: { additionalFields: { isAdmin: { type: "boolean", required: true, defaultValue: false, input: false, // Don't allow users to set this during signup returned: true, }, }, }, ``` in the options object Then using that object: ``` export const auth = betterAuth({ ...authOptions, plugins: [ ...(authOptions.plugins ?? []), customSession(async ({ user, session }) => { console.log("customSession", user, session); }, authOptions), ], }); ``` And the type of user indeed has isAdmin but the runtime doesn't....? ### Current vs. Expected behavior Have an additional prop for additionalFields : isPublic, which tells better-auth to return to getSession to client too. Or at least include all additionalFields in customSession callback, to match the typing correctly, and already making a DB request.. ### What version of Better Auth are you using? 1.3.4 ### Provide environment information ```bash - ``` ### Which area(s) are affected? (Select all that apply) Documentation, Client, Backend, Types ### Auth config (if applicable) ```typescript - already included ``` ### Additional context _No response_
GiteaMirror added the enhancement label 2026-03-13 08:54:56 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Aug 8, 2025):

This is a known gap in better-auth: additionalFields (even with returned: true) are not included in the runtime user/session object returned by getSession or customSession unless those fields are actually present in the database and handled by your adapter. The returned property only affects TypeScript types and Zod schemas, not what is sent to the client or available at runtime. So, type inference will show the field, but unless it's persisted and loaded from the DB, it won't appear in the session object you get back (source, source, source).

There is no config option to force inclusion of additionalFields in session responses beyond what is stored in the DB. If you want a field like isAdmin to be available in getSession/customSession, you need to add it to your user table and make sure your adapter includes it in the user object. The returned flag is not enforced at runtime—it's just for types and validation (source).

If you want more control, you can use a custom plugin or endpoint to postprocess the session object before returning it, but by default, only DB fields are included. This is not well documented and has caused confusion for others as well (source, source).

If you want to avoid extra DB queries, make sure all fields you need are loaded in the initial user/session fetch. There’s no built-in way to mark a field as “public” or “isPublic” for automatic exposure to the client—security and privacy are up to you to manage in your DB schema and adapter logic.

To reply, just mention @dosu.


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

@dosubot[bot] commented on GitHub (Aug 8, 2025): <!-- Answer --> This is a known gap in better-auth: additionalFields (even with returned: true) are not included in the runtime user/session object returned by getSession or customSession unless those fields are actually present in the database and handled by your adapter. The returned property only affects TypeScript types and Zod schemas, not what is sent to the client or available at runtime. So, type inference will show the field, but unless it's persisted and loaded from the DB, it won't appear in the session object you get back ([source](https://github.com/better-auth/better-auth/issues/1459), [source](https://github.com/better-auth/better-auth/issues/1194), [source](https://github.com/better-auth/better-auth/issues/2818)). There is no config option to force inclusion of additionalFields in session responses beyond what is stored in the DB. If you want a field like isAdmin to be available in getSession/customSession, you need to add it to your user table and make sure your adapter includes it in the user object. The returned flag is not enforced at runtime—it's just for types and validation ([source](https://github.com/better-auth/better-auth/blob/0fe17704048bca8d52b547eb57a53ca89e84b78c/packages/better-auth/src/db/field.ts)). If you want more control, you can use a custom plugin or endpoint to postprocess the session object before returning it, but by default, only DB fields are included. This is not well documented and has caused confusion for others as well ([source](https://github.com/better-auth/better-auth/issues/1459), [source](https://github.com/better-auth/better-auth/issues/1194)). If you want to avoid extra DB queries, make sure all fields you need are loaded in the initial user/session fetch. There’s no built-in way to mark a field as “public” or “isPublic” for automatic exposure to the client—security and privacy are up to you to manage in your DB schema and adapter logic. <!-- 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/bbe604e1-c221-4d29-88d6-3a06a0152290?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/bbe604e1-c221-4d29-88d6-3a06a0152290?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/bbe604e1-c221-4d29-88d6-3a06a0152290?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/bbe604e1-c221-4d29-88d6-3a06a0152290?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/bbe604e1-c221-4d29-88d6-3a06a0152290?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/bbe604e1-c221-4d29-88d6-3a06a0152290?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/bbe604e1-c221-4d29-88d6-3a06a0152290?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/3888)
Author
Owner

@najibghadri commented on GitHub (Aug 8, 2025):

Similare issue in: https://github.com/better-auth/better-auth/issues/1194

@najibghadri commented on GitHub (Aug 8, 2025): Similare issue in: https://github.com/better-auth/better-auth/issues/1194
Author
Owner

@najibghadri commented on GitHub (Aug 8, 2025):

Similare also: https://github.com/better-auth/better-auth/issues/2968

@najibghadri commented on GitHub (Aug 8, 2025): Similare also: https://github.com/better-auth/better-auth/issues/2968
Author
Owner

@najibghadri commented on GitHub (Aug 8, 2025):

@dosu it's definitely a bug. additionalFields not included in any of the getSessions. Then what's the point of additionalfields anyway?

@najibghadri commented on GitHub (Aug 8, 2025): @dosu it's definitely a bug. additionalFields not included in any of the getSessions. Then what's the point of additionalfields anyway?
Author
Owner

@dosubot[bot] commented on GitHub (Aug 8, 2025):

This isn't a bug—it's a design decision in Better Auth. The purpose of additionalFields is to extend your user/session schema for type inference, validation, and database migrations. However, for a field to actually show up in getSession or customSession at runtime, it must be present in the database and returned by your adapter. The returned property only affects TypeScript types and Zod schemas, not what is included in the runtime session/user object sent to the client or available in server callbacks (source).

So, additionalFields are mainly for schema extension and type safety. If you want a field like isAdmin to appear in getSession, you need to make sure it's stored in your user table and loaded by your adapter. There’s no built-in way to mark a field as “public” for automatic exposure to the client—only fields actually present in the DB and adapter output are included (source). This gap between type inference and runtime data is a known source of confusion and is not well documented (source).

If you need to expose custom fields, make sure they're persisted and loaded, or use a custom plugin to postprocess the session object before returning it.

To reply, just mention @dosu.


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

@dosubot[bot] commented on GitHub (Aug 8, 2025): <!-- Answer --> This isn't a bug—it's a design decision in Better Auth. The purpose of additionalFields is to extend your user/session schema for type inference, validation, and database migrations. However, for a field to actually show up in getSession or customSession at runtime, it must be present in the database and returned by your adapter. The returned property only affects TypeScript types and Zod schemas, not what is included in the runtime session/user object sent to the client or available in server callbacks ([source](https://github.com/better-auth/better-auth/blob/0fe17704048bca8d52b547eb57a53ca89e84b78c/packages/better-auth/src/db/field.ts)). So, additionalFields are mainly for schema extension and type safety. If you want a field like isAdmin to appear in getSession, you need to make sure it's stored in your user table and loaded by your adapter. There’s no built-in way to mark a field as “public” for automatic exposure to the client—only fields actually present in the DB and adapter output are included ([source](https://github.com/better-auth/better-auth/blob/0fe17704048bca8d52b547eb57a53ca89e84b78c/packages/better-auth/src/api/routes/session.ts)). This gap between type inference and runtime data is a known source of confusion and is not well documented ([source](https://github.com/better-auth/better-auth/issues/1194)). If you need to expose custom fields, make sure they're persisted and loaded, or use a custom plugin to postprocess the session object before returning it. <!-- 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/d89c691f-f48a-4b0c-82fd-ab820a178c0c?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/d89c691f-f48a-4b0c-82fd-ab820a178c0c?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/d89c691f-f48a-4b0c-82fd-ab820a178c0c?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/d89c691f-f48a-4b0c-82fd-ab820a178c0c?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/d89c691f-f48a-4b0c-82fd-ab820a178c0c?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/d89c691f-f48a-4b0c-82fd-ab820a178c0c?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/d89c691f-f48a-4b0c-82fd-ab820a178c0c?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/3888)
Author
Owner

@typed-sigterm commented on GitHub (Aug 10, 2025):

Hallucination of dosubot. In previous versions, inferAdditionalFields plugin can help with that, however these days it stop working either.

@typed-sigterm commented on GitHub (Aug 10, 2025): Hallucination of dosubot. In previous versions, `inferAdditionalFields` plugin can help with that, however these days it stop working either.
Author
Owner

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

You can use the custom session plugin to modify what getSession and useSession return.

https://www.better-auth.com/docs/concepts/session-management#customizing-session-response

@frectonz commented on GitHub (Aug 13, 2025): You can use the custom session plugin to modify what `getSession` and `useSession` return. https://www.better-auth.com/docs/concepts/session-management#customizing-session-response
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1670