hook parameters not properly populated in Organization plugin in SvelteKit #3018

Open
opened 2026-03-13 10:34:45 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @AEZ314 on GitHub (Mar 8, 2026).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Set up the organizations plugin
  2. define a hook. Ie, beforeDeleteOrganization: async (data, request)...
  3. debug/log the parameters. The data parameter is fine, but request is undefined

Current vs. Expected behavior

I was trying to set up organizations plugin in my SvelteKit project and realized that the hooks aren't called by the framework with correct parameters. Particularly, I was trying to implement this:

				beforeDeleteOrganization: async ({ organization, user }, request) => {
					const res = await auth.api.listOrganizations(...);

					if (res.organizations.length === 1)
						throw new APIError('NOT_ACCEPTABLE', {
							message: "Can't delete your last organization."
						});
				},

but the request parameter is undefined. Without a request parameter, I'm unable to call auth.api.listOrganizations since SvelteKit doesn't expose a await headers() function and I need to get headers from the request object.

What version of Better Auth are you using?

1.4.19

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 24.6.0: Wed Oct 15 21:12:08 PDT 2025; root:xnu-11417.140.69.703.14~1/RELEASE_ARM64_T6020",
    "release": "24.6.0",
    "cpuCount": 12,
    "cpuModel": "Apple M2 Pro",
    "totalMemory": "32.00 GB",
    "freeMemory": "0.15 GB"
  },
  "node": {
    "version": "v24.4.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.4.2"
  },
  "frameworks": [
    {
      "name": "svelte",
      "version": "^5.48.2"
    },
    {
      "name": "@sveltejs/kit",
      "version": "^2.50.1"
    }
  ],
  "databases": [
    {
      "name": "pg",
      "version": "^8.18.0"
    },
    {
      "name": "postgres",
      "version": "^3.4.8"
    },
    {
      "name": "drizzle",
      "version": "^0.45.1"
    }
  ],
  "betterAuth": {
    "version": "Unknown",
    "config": null,
    "error": "Cannot find module '$schema'\nRequire stack:\n- /Users/jack/Desktop/HelloWorld/ZaloStack/app/src/lib/server/auth.js"
  }
}

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

Backend

Auth config (if applicable)


Additional context

No response

Originally created by @AEZ314 on GitHub (Mar 8, 2026). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Set up the organizations plugin 2. define a hook. Ie, beforeDeleteOrganization: async (data, request)... 3. debug/log the parameters. The data parameter is fine, but request is undefined ### Current vs. Expected behavior I was trying to set up organizations plugin in my SvelteKit project and realized that the hooks aren't called by the framework with correct parameters. Particularly, I was trying to implement this: ``` beforeDeleteOrganization: async ({ organization, user }, request) => { const res = await auth.api.listOrganizations(...); if (res.organizations.length === 1) throw new APIError('NOT_ACCEPTABLE', { message: "Can't delete your last organization." }); }, ``` but the request parameter is undefined. Without a request parameter, I'm unable to call auth.api.listOrganizations since SvelteKit doesn't expose a await headers() function and I need to get headers from the request object. ### What version of Better Auth are you using? 1.4.19 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 24.6.0: Wed Oct 15 21:12:08 PDT 2025; root:xnu-11417.140.69.703.14~1/RELEASE_ARM64_T6020", "release": "24.6.0", "cpuCount": 12, "cpuModel": "Apple M2 Pro", "totalMemory": "32.00 GB", "freeMemory": "0.15 GB" }, "node": { "version": "v24.4.0", "env": "development" }, "packageManager": { "name": "npm", "version": "11.4.2" }, "frameworks": [ { "name": "svelte", "version": "^5.48.2" }, { "name": "@sveltejs/kit", "version": "^2.50.1" } ], "databases": [ { "name": "pg", "version": "^8.18.0" }, { "name": "postgres", "version": "^3.4.8" }, { "name": "drizzle", "version": "^0.45.1" } ], "betterAuth": { "version": "Unknown", "config": null, "error": "Cannot find module '$schema'\nRequire stack:\n- /Users/jack/Desktop/HelloWorld/ZaloStack/app/src/lib/server/auth.js" } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript ``` ### Additional context _No response_
Author
Owner

@dosubot[bot] commented on GitHub (Mar 8, 2026):

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

This is a known issue in version 1.4.19 - the request parameter is not actually passed to organization hooks. The type definition for beforeDeleteOrganization only includes the data parameter:

beforeDeleteOrganization?: (data: {
    organization: Organization & Record<string, any>;
    user: User & Record<string, any>;
}) => Promise<void>;

There's a documentation discrepancy where the docs show a request parameter that doesn't exist in the implementation - this was addressed in PR #6841, which added a ctx parameter to hooks, but that change came after 1.4.19.

Workaround for 1.4.19: Query the database directly within your hook instead of using auth.api:

beforeDeleteOrganization: async ({ organization, user }) => {
    // Direct database query (example with Drizzle)
    const memberships = await db.select()
        .from(schema.member)
        .where(eq(schema.member.userId, user.id));

    if (memberships.length === 1) {
        throw new APIError('NOT_ACCEPTABLE', {
            message: "Can't delete your last organization."
        });
    }
}

Alternatively, upgrading to a newer version should give you access to the ctx parameter with the request object.

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 (Mar 8, 2026): <!-- Greeting --> Hi @AEZ314! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> This is a known issue in version 1.4.19 - the `request` parameter is **not actually passed** to organization hooks. The [type definition for `beforeDeleteOrganization`](https://github.com/better-auth/better-auth/blob/8e0e53ed9b8918f43dd8e60194580d1357f9e0fb/packages/better-auth/src/plugins/organization/types.ts#L447-L450) only includes the data parameter: ```typescript beforeDeleteOrganization?: (data: { organization: Organization & Record<string, any>; user: User & Record<string, any>; }) => Promise<void>; ``` There's a [documentation discrepancy](https://github.com/better-auth/better-auth/blob/8e0e53ed9b8918f43dd8e60194580d1357f9e0fb/docs/content/docs/plugins/organization.mdx#L836-L841) where the docs show a `request` parameter that doesn't exist in the implementation - this was [addressed in PR #6841](https://github.com/better-auth/better-auth/issues/7733), which added a `ctx` parameter to hooks, but that change came after 1.4.19. **Workaround for 1.4.19**: Query the database directly within your hook instead of using `auth.api`: ```typescript beforeDeleteOrganization: async ({ organization, user }) => { // Direct database query (example with Drizzle) const memberships = await db.select() .from(schema.member) .where(eq(schema.member.userId, user.id)); if (memberships.length === 1) { throw new APIError('NOT_ACCEPTABLE', { message: "Can't delete your last organization." }); } } ``` Alternatively, upgrading to a newer version should give you access to the `ctx` parameter with the request object. <!-- 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/68b6c970-2c8b-4a79-8171-f355d3354db3?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/68b6c970-2c8b-4a79-8171-f355d3354db3?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/68b6c970-2c8b-4a79-8171-f355d3354db3?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/68b6c970-2c8b-4a79-8171-f355d3354db3?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/68b6c970-2c8b-4a79-8171-f355d3354db3?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/68b6c970-2c8b-4a79-8171-f355d3354db3?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/68b6c970-2c8b-4a79-8171-f355d3354db3?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%20known%20issue%20in%20version%201.4.19%20-%20the%20%60request%60%20parameter%20is%20%2A%2Anot%20actually%20passed%2A%2A%20to%20organization%20hooks.%20The%20%5Btype%20definition%20for%20%60beforeDeleteOrganization%60%5D%28https%3A//github.com/better-auth/better-auth/blob/8e0e53ed9b8918f43dd8e60194580d1357f9e0fb/packages/better-auth/src/plugins/organization/types.ts%23L447-L450%29%20only%20includes%20the%20data%20parameter%3A%0A%0A%60%60%60typescript%0AbeforeDeleteOrganization%3F%3A%20%28data%3A%20%7B%0A%20%20%20%20organization%3A%20Organization%20%26%20Record%3Cstring%2C%20any%3E%3B%0A%20%20%20%20user%3A%20User%20%26%20Record%3Cstring%2C%20any%3E%3B%0A%7D%29%20%3D%3E%20Promise%3Cvoid%3E%3B%0A%60%60%60%0A%0AThere%27s%20a%20%5Bdocumentation%20discrepancy%5D%28https%3A//github.com/better-auth/better-auth/blob/8e0e53ed9b8918f43dd8e60194580d1357f9e0fb/docs/content/docs/plugins/organization.mdx%23L836-L841%29%20where%20the%20docs%20show%20a%20%60request%60%20parameter%20that%20doesn%27t%20exist%20in%20the%20implementation%20-%20this%20was%20%5Baddressed%20in%20PR%20%236841%5D%28https%3A//github.com/better-auth/better-auth/issues/7733%29%2C%20which%20added%20a%20%60ctx%60%20parameter%20to%20hooks%2C%20but%20that%20change%20came%20after%201.4.19.%0A%0A%2A%2AWorkaround%20for%201.4.19%2A%2A%3A%20Query%20the%20database%20directly%20within%20your%20hook%20instead%20of%20using%20%60auth.api%60%3A%0A%0A%60%60%60typescript%0AbeforeDeleteOrganization%3A%20async%20%28%7B%20organization%2C%20user%20%7D%29%20%3D%3E%20%7B%0A%20%20%20%20//%20Direct%20database%20query%20%28example%20with%20Drizzle%29%0A%20%20%20%20const%20memberships%20%3D%20await%20db.select%28%29%0A%20%20%20%20%20%20%20%20.from%28schema.member%29%0A%20%20%20%20%20%20%20%20.where%28eq%28schema.member.userId%2C%20user.id%29%29%3B%0A%0A%20%20%20%20if%20%28memberships.length%20%3D%3D%3D%201%29%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20APIError%28%27NOT_ACCEPTABLE%27%2C%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20message%3A%20%22Can%27t%20delete%20your%20last%20organization.%22%0A%20%20%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0AAlternatively%2C%20upgrading%20to%20a%20newer%20version%20should%20give%20you%20access%20to%20the%20%60ctx%60%20parameter%20with%20the%20request%20object.)&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/8494)
Author
Owner

@AEZ314 commented on GitHub (Mar 8, 2026):

No, this isn't version related. I just updated to a newer version and when I inspect the source code this is what I saw:

		if (options?.organizationHooks?.beforeDeleteOrganization) await options.organizationHooks.beforeDeleteOrganization({
			organization: org,
			user: session.user
		});

This is how the hook is called. No request object is passed. The docs are misleading.

@AEZ314 commented on GitHub (Mar 8, 2026): No, this isn't version related. I just updated to a newer version and when I inspect the source code this is what I saw: ``` if (options?.organizationHooks?.beforeDeleteOrganization) await options.organizationHooks.beforeDeleteOrganization({ organization: org, user: session.user }); ``` This is how the hook is called. No request object is passed. The docs are misleading.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#3018