[GH-ISSUE #6206] Type error.body.code as string literal enum #19076

Closed
opened 2026-04-15 17:52:01 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @lensbart on GitHub (Nov 22, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/6206

It would be great if we could do a switch/case with exhaustiveness check for errors, like so:

	try {
		const result = await auth.api.acceptInvitation({
			body: { invitationId },
			headers: request.headers,
		})
	} catch (error) {
		if (error instanceof APIError && error.body != null) {
			switch (error.body.code) {
				case "INVITATION_NOT_FOUND":
					// do something
			}
		}
	}

Using switch/case with a string literal enum works well with @typescript-eslint/switch-exhaustiveness-check: this allows you to get warned at build time if you forgot to handle an enum member.

Thanks for your consideration!

Describe the solution you'd like

error.body.code is typed as "INVITATION_NOT_FOUND" | "SOMETHING_ELSE" | "ETC."

Originally created by @lensbart on GitHub (Nov 22, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/6206 It would be great if we could do a `switch`/`case` with exhaustiveness check for errors, like so: ```ts try { const result = await auth.api.acceptInvitation({ body: { invitationId }, headers: request.headers, }) } catch (error) { if (error instanceof APIError && error.body != null) { switch (error.body.code) { case "INVITATION_NOT_FOUND": // do something } } } ``` Using `switch`/`case` with a string literal enum works well with [`@typescript-eslint/switch-exhaustiveness-check`](https://typescript-eslint.io/rules/switch-exhaustiveness-check): this allows you to get warned at build time if you forgot to handle an enum member. Thanks for your consideration! ### Describe the solution you'd like `error.body.code` is typed as `"INVITATION_NOT_FOUND" | "SOMETHING_ELSE" | "ETC."`
GiteaMirror added the lockedenhancement labels 2026-04-15 17:52:01 -05:00
Author
Owner

@lensbart commented on GitHub (Nov 22, 2025):

Even better would be to include the errors as part of the domain (in the typed response from e.g. auth.api.acceptInvitation), so that try/catch would only be needed for generic errors unrelated to Better Auth.

Thanks!

<!-- gh-comment-id:3567016436 --> @lensbart commented on GitHub (Nov 22, 2025): Even better would be to include the errors as part of the domain (in the typed response from e.g. `auth.api.acceptInvitation`), so that `try`/`catch` would only be needed for generic errors unrelated to Better Auth. Thanks!
Author
Owner

@dosubot[bot] commented on GitHub (Nov 22, 2025):

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

Better Auth currently throws domain-specific errors (like "INVITATION_NOT_FOUND") as exceptions using APIError, rather than including them in the typed response of API methods such as auth.api.acceptInvitation. This means you need to use try/catch to handle these errors, and they aren't part of a discriminated union or Result type in the method's return signature. There isn't a built-in way to know at compile time which domain errors a method might throw, nor is there a centralized, typesafe union of all possible error codes—error codes are defined in per-feature constants and must be manually aggregated if you want exhaustive type checking in your own code (source, source).

There have been feature requests to expose error codes as enums or string literal unions for better type safety and exhaustiveness checking, but this isn't implemented yet (source). For now, the recommended approach is to catch APIError, inspect the code or message, and handle errors accordingly. If you want to improve type safety, you can manually aggregate error codes into a union type for your own switch/case handling (source).

Moving domain errors into the typed response (e.g., using a Result type or discriminated union) would require a significant change to the API's design and error handling patterns.

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:3567018064 --> @dosubot[bot] commented on GitHub (Nov 22, 2025): <!-- Greeting --> Hi @lensbart! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> Better Auth currently throws domain-specific errors (like `"INVITATION_NOT_FOUND"`) as exceptions using `APIError`, rather than including them in the typed response of API methods such as `auth.api.acceptInvitation`. This means you need to use `try`/`catch` to handle these errors, and they aren't part of a discriminated union or `Result` type in the method's return signature. There isn't a built-in way to know at compile time which domain errors a method might throw, nor is there a centralized, typesafe union of all possible error codes—error codes are defined in per-feature constants and must be manually aggregated if you want exhaustive type checking in your own code ([source](https://github.com/better-auth/better-auth/issues/5110), [source](https://github.com/better-auth/better-auth/blob/54852e30e0bbcb9f7a0e8dfc284447915adb706f/packages/better-auth/src/plugins/organization/routes/crud-invites.ts#L175-L659)). There have been feature requests to expose error codes as enums or string literal unions for better type safety and exhaustiveness checking, but this isn't implemented yet ([source](https://github.com/better-auth/better-auth/issues/3269)). For now, the recommended approach is to catch `APIError`, inspect the `code` or `message`, and handle errors accordingly. If you want to improve type safety, you can manually aggregate error codes into a union type for your own switch/case handling ([source](https://github.com/better-auth/better-auth/issues/5110)). Moving domain errors into the typed response (e.g., using a `Result` type or discriminated union) would require a significant change to the API's design and error handling patterns. <!-- 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/50186733-bf1f-4f2b-beff-1c3490bd372e?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/50186733-bf1f-4f2b-beff-1c3490bd372e?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/50186733-bf1f-4f2b-beff-1c3490bd372e?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/50186733-bf1f-4f2b-beff-1c3490bd372e?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/50186733-bf1f-4f2b-beff-1c3490bd372e?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/50186733-bf1f-4f2b-beff-1c3490bd372e?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/50186733-bf1f-4f2b-beff-1c3490bd372e?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=Better%20Auth%20currently%20throws%20domain-specific%20errors%20%28like%20%60%22INVITATION_NOT_FOUND%22%60%29%20as%20exceptions%20using%20%60APIError%60%2C%20rather%20than%20including%20them%20in%20the%20typed%20response%20of%20API%20methods%20such%20as%20%60auth.api.acceptInvitation%60.%20This%20means%20you%20need%20to%20use%20%60try%60/%60catch%60%20to%20handle%20these%20errors%2C%20and%20they%20aren%27t%20part%20of%20a%20discriminated%20union%20or%20%60Result%60%20type%20in%20the%20method%27s%20return%20signature.%20There%20isn%27t%20a%20built-in%20way%20to%20know%20at%20compile%20time%20which%20domain%20errors%20a%20method%20might%20throw%2C%20nor%20is%20there%20a%20centralized%2C%20typesafe%20union%20of%20all%20possible%20error%20codes%E2%80%94error%20codes%20are%20defined%20in%20per-feature%20constants%20and%20must%20be%20manually%20aggregated%20if%20you%20want%20exhaustive%20type%20checking%20in%20your%20own%20code%20%28%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/issues/5110%29%2C%20%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/blob/54852e30e0bbcb9f7a0e8dfc284447915adb706f/packages/better-auth/src/plugins/organization/routes/crud-invites.ts%23L175-L659%29%29.%0A%0AThere%20have%20been%20feature%20requests%20to%20expose%20error%20codes%20as%20enums%20or%20string%20literal%20unions%20for%20better%20type%20safety%20and%20exhaustiveness%20checking%2C%20but%20this%20isn%27t%20implemented%20yet%20%28%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/issues/3269%29%29.%20For%20now%2C%20the%20recommended%20approach%20is%20to%20catch%20%60APIError%60%2C%20inspect%20the%20%60code%60%20or%20%60message%60%2C%20and%20handle%20errors%20accordingly.%20If%20you%20want%20to%20improve%20type%20safety%2C%20you%20can%20manually%20aggregate%20error%20codes%20into%20a%20union%20type%20for%20your%20own%20switch/case%20handling%20%28%5Bsource%5D%28https%3A//github.com/better-auth/better-auth/issues/5110%29%29.%20%0A%0AMoving%20domain%20errors%20into%20the%20typed%20response%20%28e.g.%2C%20using%20a%20%60Result%60%20type%20or%20discriminated%20union%29%20would%20require%20a%20significant%20change%20to%20the%20API%27s%20design%20and%20error%20handling%20patterns.)&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/6206)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#19076