Trouble inferring types on client side (1.3.4)
@Better Auth Hey, I was trying to infer some types on client side:
type AuthContextValue = {
member: typeof authClient.$Infer.Member | null;
user: typeof authClient.$Infer.Session.user | null;
session: typeof authClient.$Infer.Session.session | null;
activeOrganization: typeof authClient.$Infer.ActiveOrganization | null;
}
export const authClient = createAuthClient({
baseURL: env.VITE_BASE_URL,
plugins: [
adminClient(),
organizationClient({
allowUserToCreateOrganization: true,
cancelPendingInvitationsOnReInvite: true,
invitationLimit: 1,
organizationDeletion: {
disabled: true,
},
teams: {
enabled: false,
},
}),
phoneNumberClient(),
emailOTPClient(),
inferAdditionalFields({
user: {
role: {
type: "string",
},
phoneNumber: {
type: "string",
required: true,
input: true,
unique: true,
},
referralCode: {
type: "string",
required: true,
input: true,
},
},
}),
],
})
This is my auth-client.ts
I have an error here activeOrganization: typeof authClient.$Infer.ActiveOrganization | null; and also here member: typeof authClient.$Infer.Member | null;
Property 'Member' does not exist on type '{ Session: { user: { id: string; email: string; emailVerified: boolean; name: string; createdAt: Date; updatedAt: Date; image?: string | null | undefined; }; session: { id: string; userId: string; ... 5 more ...; userAgent?: string | ... 1 more ... | undefined; }; }; }'.ts(2339).
Property 'ActiveOrganization' does not exist on type '{ Session: { user: { id: string; email: string; emailVerified: boolean; name: string; createdAt: Date; updatedAt: Date; image?: string | null | undefined; }; session: { id: string; userId: string; ... 5 more ...; userAgent?: string | ... 1 more ... | undefined; }; }; }'.ts(2339)
15 Replies
It looks like the error appears because your current Better Auth client isn’t exposing the types for Member and ActiveOrganization on its $Infer object. In Better Auth, types like ActiveOrganization and Member are only added to the inference if the corresponding plugin (and its proper schema) is registered on the server and then passed to the client through functions like inferAdditionalFields or with a dedicated organization client setup [3].
A few things to check or try:
1. Verify that on the server side you’ve configured the organization plugin to include additional fields (and a member extension if applicable). The inference for ActiveOrganization (and its related types) is only added when the server configuration exposes it. If your server config does not include those aspects, the client’s $Infer object won’t have them.
2. Ensure that on the client you are using the proper organization client plugin (and if needed, an additional helper like inferOrgAdditionalFields) so that the client is aware of the server’s extended types. See the guidelines on inferring additional fields from the organization plugin [7].
3. If you’re sure your server-side config is correct, check if you might need to update (or re-import) your type definitions from the organization plugin. Sometimes, the $Infer object is limited to only what the plugins make available. In this case, if Member isn’t exported by the plugin you’re using, you may want to use the types that come with the organization plugin directly or extend your own definitions.
In summary, the error stems from the fact that Better Auth doesn’t expose “Member” or “ActiveOrganization” on $Infer by default—it depends on how the plugins are configured and inferred from the server. Double-check your server config
GitHub
better-auth/better-auth
The most comprehensive authentication framework for TypeScript - better-auth/better-auth
and ensure that your client plugins (and any additional fields inference plugins) are set up accordingly [1], [9].
Sources:
[1] Type mismatch authClient Active Organization
[3] TypeScript | Better Auth
[7] Organization additional fields not returning new fields
[9] Property 'useActiveOrganization' does not exist on type. (Minimal Reproduction repo provided)
GitHub
better-auth/better-auth
The most comprehensive authentication framework for TypeScript - better-auth/better-auth
GitHub
better-auth/better-auth
The most comprehensive authentication framework for TypeScript - better-auth/better-auth
GitHub
Type mismatch authClient Active Organization · Issue #2285 · bett...
Is this suited for github? Yes, this is suited for github To Reproduce Mismatch between the type returned by authClient.useActiveOrganization and typeof authClient.$Infer.ActiveOrganization export ...
TypeScript | Better Auth
Better Auth TypeScript integration.
GitHub
Organization additional fields not returning new fields · Issue #3...
Is this suited for github? Yes, this is suited for github To Reproduce To reproduce, just use my configuration down below and try get the field publicId on the data returned by useActiveOrganizatio...
@Better Auth here's the full auth-client.ts file
import { createAuthClient } from "better-auth/react"
import {
adminClient,
inferAdditionalFields,
organizationClient,
phoneNumberClient,
emailOTPClient,
} from "better-auth/client/plugins"
import env from "./env"
export const authClient = createAuthClient({
baseURL: env.VITE_BASE_URL,
plugins: [
adminClient(),
organizationClient({
allowUserToCreateOrganization: true,
cancelPendingInvitationsOnReInvite: true,
invitationLimit: 1,
organizationDeletion: {
disabled: true,
},
teams: {
enabled: false,
},
}),
phoneNumberClient(),
emailOTPClient(),
inferAdditionalFields({
user: {
role: {
type: "string",
},
phoneNumber: {
type: "string",
required: true,
input: true,
unique: true,
},
referralCode: {
type: "string",
required: true,
input: true,
},
},
}),
],
})
Your auth‐client.ts configuration looks well set up! You're using several key plugins—adminClient, organizationClient, phoneNumberClient, emailOTPClient, and inferAdditionalFields—which is in line with the typical Better Auth client setup [4].
A couple of things to keep in mind:
• With the organizationClient options, you’ve configured settings like allowing user creation of organizations, cancelling pending invitations on re-invite, and disabling organization deletion. This setup is consistent with our organization plugin best practices [6].
• For inferAdditionalFields, you’re manually specifying the user additional fields (role, phoneNumber, referralCode). This is a good practice—especially if your server/client projects are separate—to ensure type inference without exposing unneeded server details [9].
Overall, everything appears to be correctly configured. If you run into any issues (especially around type inference or field exposure), double-check that the additional field definitions on your client match the server configuration. Otherwise, your client file looks ready to roll!
Sources:
[4] Client | Better Auth
[6] Organization | Better Auth
[9] TypeScript | Better Auth
Client | Better Auth
Better Auth client library for authentication.
Organization | Better Auth
The organization plugin allows you to manage your organization's members and teams.
@Better Auth On point no.2 Do i add the inferOrgAdditionalFields inside inferAdditionalFields or is it it's own plugin? Could you show me an example since im not in a mono repo and cant use something line <typeof auth> to infer additional fields
You're going to want to use inferOrgAdditionalFields as its own plugin rather than nesting it inside inferAdditionalFields. Since you're not in a monorepo and can't rely on referencing your server auth object via a generic (like <typeof auth>), you can call inferOrgAdditionalFields without that generic parameter.
For example, if you're setting up your client config, your code might look like this:
This example shows that inferOrgAdditionalFields is applied directly inside the organization client plugin configuration and isn’t nested within inferAdditionalFields [8]. This setup is ideal when you're not able to use the generic type reference from your server auth configuration.
Sources:
[8] docs(org):
inferOrgAdditionalFields
has wrong import pathGitHub
Build software better, together
GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.

GitHub
docs(org):
inferOrgAdditionalFields
has wrong import path by ping...The newly introduced inferOrgAdditionalFields has the wrong import path in the docs.
Closes #3733
Summary by cubic
Fixed the import path for inferOrgAdditionalFields in the organization plugin do...
@Better Auth This is my server side config auth.ts
organization({
allowUserToCreateOrganization: async ({ id }) => {
return await isUserOrgOwner(id);
},
cancelPendingInvitationsOnReInvite: true,
invitationLimit: 1,
organizationDeletion: {
disabled: true,
},
teams: {
enabled: false,
},
}),
I am still not able to get the types inferred on client side using my current auth-client.ts setup. What should I do?
It looks like your client isn’t picking up the organization plugin’s types because the client setup isn’t correctly wired to your server’s auth type. To fix this, ensure that on the client side you’re using the dedicated organization client plugin and passing your server-side auth instance as a type parameter.
For example, adjust your auth‐client.ts like so:
This approach tells the client plugin exactly what types to expect, ensuring that the inferred types (including the organization‑specific ones) are available on the client side [2][3].
Also verify that your TypeScript configuration has strict mode enabled because Better Auth is designed to work optimally with strict type inference [3].
Sources:
[2] Organization | Better Auth
[3] TypeScript | Better Auth
Organization | Better Auth
The organization plugin allows you to manage your organization's members and teams.
TypeScript | Better Auth
Better Auth TypeScript integration.
@Better Auth Since i'm not on a mono repo I cant use <typeof auth>
You're correct—when your client and server are in separate projects, the approach using
<typeof auth>
(which automatically infers the additional fields) isn’t applicable. In that case, the recommendation is to manually specify your additional field definitions in your client-side configuration. This approach ensures you only expose what’s necessary, helping to avoid inadvertently leaking server-side details [8].
For example, instead of writing:
You would manually define the fields like so:
This way, you maintain type safety without relying on server-only type inference in a non-monorepo setup [8].
Sources:
[8] TypeScript | Better AuthTypeScript | Better Auth
Better Auth TypeScript integration.
@Better Auth One more quick question, when sending an invitation. Is it possible to also extend the invitation schema to include the organizationName, organizationSlug and inviterName?
Yes, you can extend the invitation schema to include additional fields like organizationName, organizationSlug, and inviterName. Starting with Better Auth v1.3, you can use the additionalFields option in your organization plugin configuration to add custom fields to the invitation model. This means you can specify these extra fields in your configuration, and they will be automatically included in both the API request and response payloads, helping you tailor the schema to your application's needs [2], [17].
Sources:
[2] Organization | Better Auth
[17] feat(org): additionalFields for org, member, invitation & team
GitHub
Build software better, together
GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.

Organization | Better Auth
The organization plugin allows you to manage your organization's members and teams.
GitHub
feat(org): additionalFields for org, member, invitation & team by p...
docs
tests
Summary by cubic
Added support for custom additionalFields on organization, member, invitation, and team models, allowing users to define extra fields in the organization plugin schem...
@Better Auth Could you show me an example of how I can add the org name and inviter name when sending an invite in the db? I don't want to just add it to the email but also to the db.
Below is one way to do this. The idea is to extend the invitation record in your database to store extra fields (for example, organizationName and inviterName) and then update those fields when sending the invitation.
For instance, you could extend your Better Auth configuration to add additional fields to the invitation schema. Then, in your custom sendInvitationEmail function, after sending the email, you update (or create) the invitation record with these extra properties.
Here's an example:
// Send the invitation email await sendOrganizationInvitation({ email: data.email, invitedByUsername: data.inviter.user.name, teamName: data.organization.name, inviteLink, });
// Now update the invitation record in the database // This assumes your invitation record has been set up with additionalFields await db.update({ model: "invitation", where: { id: data.id }, update: { organizationName: data.organization.name, inviterName: data.inviter.user.name
``ts
import { betterAuth } from "better-auth";
import { organization } from "better-auth/plugins";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { sendOrganizationInvitation } from "./email";
import db from "./db"; // your database instance
export const auth = betterAuth({
database: drizzleAdapter(db, { provider: "pg" }),
schema: {
// Extend the invitation schema to include extra fields
invitation: {
additionalFields: {
organizationName: { type: "string" },
inviterName: { type: "string" }
}
},
// ... you can extend other models as needed
},
plugins: [
organization({
async sendInvitationEmail(data) {
const inviteLink =
https://example.com/accept-invitation/${data.id}`;
// Send the invitation email await sendOrganizationInvitation({ email: data.email, invitedByUsername: data.inviter.user.name, teamName: data.organization.name, inviteLink, });
// Now update the invitation record in the database // This assumes your invitation record has been set up with additionalFields await db.update({ model: "invitation", where: { id: data.id }, update: { organizationName: data.organization.name, inviterName: data.inviter.user.name
}
});
},
}),
],
});
```
In this example:
1. We extend the invitation schema by providing two additional fields—organizationName and inviterName. This lets Better Auth know to expect and store these values [1].
2. In the custom sendInvitationEmail implementation, after sending the email, the code calls your database adapter’s update method to store the extra data. This way, the invitation record contains both the original invitation data and your custom fields [1], [11]. This approach adheres to Better Auth’s extensibility principles while leveraging your existing adapter (see also the discussion on extending fields in the original organization invitation examples [1]). Feel free to adjust the implementation to fit your specific database adapter or hook setup. Sources: [1] Organization | Better Auth [11] Database | Better Auth
1. We extend the invitation schema by providing two additional fields—organizationName and inviterName. This lets Better Auth know to expect and store these values [1].
2. In the custom sendInvitationEmail implementation, after sending the email, the code calls your database adapter’s update method to store the extra data. This way, the invitation record contains both the original invitation data and your custom fields [1], [11]. This approach adheres to Better Auth’s extensibility principles while leveraging your existing adapter (see also the discussion on extending fields in the original organization invitation examples [1]). Feel free to adjust the implementation to fit your specific database adapter or hook setup. Sources: [1] Organization | Better Auth [11] Database | Better Auth
Organization | Better Auth
The organization plugin allows you to manage your organization's members and teams.