[Bug] Admin Plugin Crash #2886

Closed
opened 2026-03-13 10:25:38 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @besellem on GitHub (Feb 17, 2026).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

When using the admin plugin, a TypeError occurs in the session.create.before hook if the user associated with the session cannot be found. This seems to happen when ctx.context.internalAdapter.findUserById(session.userId) returns null or undefined, and the code subsequently attempts to access user.banned.

This issue was observed in a production environment using better-auth@1.4.18 with the Prisma adapter.

Current vs. Expected behavior

The plugin should gracefully handle cases where the user is not found, or throw a more descriptive error.

What version of Better Auth are you using?

1.4.18

System info

Better Auth Version: 1.4.18
Framework:           Next.js 16.1.6
Adapter:             Prisma (PostgreSQL) 7.4.0
System Version:      macOS 15.7.4

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

Client, Backend

Auth config (if applicable)

export const auth = betterAuth({
	database: prismaAdapter(db, {
		provider: 'postgresql'
	}),
	trustedOrigins: [
		process.env.NEXT_PUBLIC_APP_URL!,
	],
	advanced: {
		cookiePrefix: 'strateline',
		// useSecureCookies: true,
	},
	telemetry: {
		enabled: false
	},
	rateLimit: {
		enabled: true,
		window: 10,
		max: 100,
		storage: 'database',
		modelName: 'rateLimit',
	},
	plugins: [
		admin(),
		magicLink({
			sendMagicLink: async ({ email, token, url }: { email: string; token: string; url: string }) => {
				await sendMagicLinkEmail({
					to: email,
					magicLinkUrl: url,
				});
			},
			expiresIn: 60 * 10, // 10 minutes
		}),
		nextCookies() // make sure this is the last plugin in the array
	],


	/**
	 * Database tables and models
	 */
	session: {
		expiresIn: 60 * 60 * 24 * 7, // 7 days
		updateAge: 60 * 60 * 24, // 1 day (every 1 day the session expiration is updated)
	},

	/**
	 * Email Verification Configuration
	 */
	emailVerification: {
		sendOnSignUp: true,
		autoSignInAfterVerification: true,
		sendVerificationEmail: async ({ user, url }: { user: { email: string; name: string }; url: string }) => {
			await sendVerificationEmail({
				to: user.email,
				userName: user.name,
				verificationUrl: url,
			});
		},
	},
})

Additional context

No response

Originally created by @besellem on GitHub (Feb 17, 2026). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce When using the admin plugin, a TypeError occurs in the session.create.before hook if the user associated with the session cannot be found. This seems to happen when ctx.context.internalAdapter.findUserById(session.userId) returns null or undefined, and the code subsequently attempts to access user.banned. This issue was observed in a production environment using better-auth@1.4.18 with the Prisma adapter. ### Current vs. Expected behavior The plugin should gracefully handle cases where the user is not found, or throw a more descriptive error. ### What version of Better Auth are you using? 1.4.18 ### System info ```bash Better Auth Version: 1.4.18 Framework: Next.js 16.1.6 Adapter: Prisma (PostgreSQL) 7.4.0 System Version: macOS 15.7.4 ``` ### Which area(s) are affected? (Select all that apply) Client, Backend ### Auth config (if applicable) ```typescript export const auth = betterAuth({ database: prismaAdapter(db, { provider: 'postgresql' }), trustedOrigins: [ process.env.NEXT_PUBLIC_APP_URL!, ], advanced: { cookiePrefix: 'strateline', // useSecureCookies: true, }, telemetry: { enabled: false }, rateLimit: { enabled: true, window: 10, max: 100, storage: 'database', modelName: 'rateLimit', }, plugins: [ admin(), magicLink({ sendMagicLink: async ({ email, token, url }: { email: string; token: string; url: string }) => { await sendMagicLinkEmail({ to: email, magicLinkUrl: url, }); }, expiresIn: 60 * 10, // 10 minutes }), nextCookies() // make sure this is the last plugin in the array ], /** * Database tables and models */ session: { expiresIn: 60 * 60 * 24 * 7, // 7 days updateAge: 60 * 60 * 24, // 1 day (every 1 day the session expiration is updated) }, /** * Email Verification Configuration */ emailVerification: { sendOnSignUp: true, autoSignInAfterVerification: true, sendVerificationEmail: async ({ user, url }: { user: { email: string; name: string }; url: string }) => { await sendVerificationEmail({ to: user.email, userName: user.name, verificationUrl: url, }); }, }, }) ``` ### Additional context _No response_
GiteaMirror added the bug label 2026-03-13 10:25:38 -05:00
Author
Owner

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

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

This is a confirmed bug in v1.4.18. The admin plugin's session.create.before hook doesn't check if the user is null before accessing user.banned:

const user = (await ctx.context.internalAdapter.findUserById(
    session.userId,
)) as UserWithRole;

if (user.banned) {  // ← user could be null here

There's also a related transaction bug in v1.4.18 where findUserById can return null due to incorrect adapter usage that bypasses the transaction context.

This has been fixed in newer versions through several PRs:

  • PR #4649: Added null checks before user operations
  • PR #6418: Added early return when userId is falsy

Recommendation: Upgrade to the latest version of better-auth to resolve this issue.

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

@dosubot[bot] commented on GitHub (Feb 17, 2026): <!-- Greeting --> Hi @besellem! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> This is a confirmed bug in v1.4.18. The [admin plugin's session.create.before hook](https://github.com/better-auth/better-auth/blob/d3b579e42a707a9037a9210ad14611366b745d2a/packages/better-auth/src/plugins/admin/admin.ts#L83-L126) doesn't check if the user is null before accessing `user.banned`: ```typescript const user = (await ctx.context.internalAdapter.findUserById( session.userId, )) as UserWithRole; if (user.banned) { // ← user could be null here ``` There's also a [related transaction bug in v1.4.18](https://github.com/better-auth/better-auth/issues/7798) where `findUserById` can return null due to incorrect adapter usage that bypasses the transaction context. **This has been fixed** in newer versions through several PRs: - [PR #4649](https://github.com/better-auth/better-auth/pull/4649): Added null checks before user operations - [PR #6418](https://github.com/better-auth/better-auth/pull/6418): Added early return when userId is falsy **Recommendation**: Upgrade to the latest version of better-auth to resolve this issue. <!-- 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/ccfc5283-7c8d-4da4-9d25-2cbae4e03039?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/ccfc5283-7c8d-4da4-9d25-2cbae4e03039?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/ccfc5283-7c8d-4da4-9d25-2cbae4e03039?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/ccfc5283-7c8d-4da4-9d25-2cbae4e03039?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/ccfc5283-7c8d-4da4-9d25-2cbae4e03039?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/ccfc5283-7c8d-4da4-9d25-2cbae4e03039?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/ccfc5283-7c8d-4da4-9d25-2cbae4e03039?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=This%20is%20a%20confirmed%20bug%20in%20v1.4.18.%20The%20%5Badmin%20plugin%27s%20session.create.before%20hook%5D%28https%3A//github.com/better-auth/better-auth/blob/d3b579e42a707a9037a9210ad14611366b745d2a/packages/better-auth/src/plugins/admin/admin.ts%23L83-L126%29%20doesn%27t%20check%20if%20the%20user%20is%20null%20before%20accessing%20%60user.banned%60%3A%0A%0A%60%60%60typescript%0Aconst%20user%20%3D%20%28await%20ctx.context.internalAdapter.findUserById%28%0A%20%20%20%20session.userId%2C%0A%29%29%20as%20UserWithRole%3B%0A%0Aif%20%28user.banned%29%20%7B%20%20//%20%E2%86%90%20user%20could%20be%20null%20here%0A%60%60%60%0A%0AThere%27s%20also%20a%20%5Brelated%20transaction%20bug%20in%20v1.4.18%5D%28https%3A//github.com/better-auth/better-auth/issues/7798%29%20where%20%60findUserById%60%20can%20return%20null%20due%20to%20incorrect%20adapter%20usage%20that%20bypasses%20the%20transaction%20context.%0A%0A%2A%2AThis%20has%20been%20fixed%2A%2A%20in%20newer%20versions%20through%20several%20PRs%3A%0A-%20%5BPR%20%234649%5D%28https%3A//github.com/better-auth/better-auth/pull/4649%29%3A%20Added%20null%20checks%20before%20user%20operations%0A-%20%5BPR%20%236418%5D%28https%3A//github.com/better-auth/better-auth/pull/6418%29%3A%20Added%20early%20return%20when%20userId%20is%20falsy%0A%0A%2A%2ARecommendation%2A%2A%3A%20Upgrade%20to%20the%20latest%20version%20of%20better-auth%20to%20resolve%20this%20issue.)&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/8022)
Author
Owner

@besellem commented on GitHub (Feb 17, 2026):

This has been fixed in the beta, right ?

@besellem commented on GitHub (Feb 17, 2026): This has been fixed in the beta, right ?
Author
Owner

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

Yes, this has been fixed. PR #4649 added explicit user existence checks before banning, and PR #5701 fixed the type mismatch for banned on UserWithRole. Both were merged in late 2025, so the fix should be available in the current beta and recent stable releases.

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

@dosubot[bot] commented on GitHub (Feb 17, 2026): <!-- Answer --> Yes, this has been fixed. [PR #4649](https://github.com/better-auth/better-auth/pull/4649) added explicit user existence checks before banning, and [PR #5701](https://github.com/better-auth/better-auth/pull/5701) fixed the type mismatch for `banned` on `UserWithRole`. Both were merged in late 2025, so the fix should be available in the current beta and recent stable releases. <!-- 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/8f1b49cb-e654-48e8-adcc-d5aa9f758ff9?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/8f1b49cb-e654-48e8-adcc-d5aa9f758ff9?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/8f1b49cb-e654-48e8-adcc-d5aa9f758ff9?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/8f1b49cb-e654-48e8-adcc-d5aa9f758ff9?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/8f1b49cb-e654-48e8-adcc-d5aa9f758ff9?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/8f1b49cb-e654-48e8-adcc-d5aa9f758ff9?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/8f1b49cb-e654-48e8-adcc-d5aa9f758ff9?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=Yes%2C%20this%20has%20been%20fixed.%20%5BPR%20%234649%5D%28https%3A//github.com/better-auth/better-auth/pull/4649%29%20added%20explicit%20user%20existence%20checks%20before%20banning%2C%20and%20%5BPR%20%235701%5D%28https%3A//github.com/better-auth/better-auth/pull/5701%29%20fixed%20the%20type%20mismatch%20for%20%60banned%60%20on%20%60UserWithRole%60.%20Both%20were%20merged%20in%20late%202025%2C%20so%20the%20fix%20should%20be%20available%20in%20the%20current%20beta%20and%20recent%20stable%20releases.)&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/8022)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2886