Build error in Astro with Cloudflare adapter when importing better-auth/plugins in middleware on prerendered pages: Invalid property descriptor in Request.headers #293

Closed
opened 2026-03-13 07:41:00 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @avanderbergh on GitHub (Nov 28, 2024).

Describe the bug
When importing any plugin from better-auth/plugins in an Astro middleware using the Cloudflare adapter, there is a side-effect that modifies the Request prototype.

Specifically, it adds a map property to the default Headers object when a new Request is created without headers. This causes a build error when running astro build to build a static page (prerender = true). The error message reads:

Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>

The error occurs in astro/dist/core/request.js, when trying to add a getter to request.headers which already has a value, leading to a conflict.

To Reproduce
To reproduce the issue, please refer to the following repository which demonstrates the error: https://github.com/avanderbergh/better-auth-astro-issue

Steps for understanding the behavior:

  1. Import any plugin from better-auth/plugins in an Astro middleware (middleware.ts).
    import { defineMiddleware } from "astro:middleware";
    import "better-auth/plugins";
    console.log(new Request("https://example.com").headers); // Logs as `Headers { map: {} }`
    
  2. Use the Cloudflare adapter (@astrojs/cloudflare).
  3. Run astro build with export const prerender = true on a page.
  4. Observe the build error:
    Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>
    

Expected behavior
The build should complete successfully without modifying the Request prototype and without causing errors related to property descriptors.

Screenshots
N/A

Additional context

  • The error is specific to the @astrojs/cloudflare adapter.
  • The suspected cause is a side-effect from better-auth plugins, which rely on better-fetch to replace the fetch function.
  • A repository that reproduces the issue is available here: https://github.com/avanderbergh/better-auth-astro-issue.
  • I have also opened an issue on Astro to handle this more gracefully instead of breaking the build.
Originally created by @avanderbergh on GitHub (Nov 28, 2024). **Describe the bug** When importing any plugin from `better-auth/plugins` in an Astro middleware using the Cloudflare adapter, there is a side-effect that modifies the `Request` prototype. Specifically, it adds a `map` property to the default `Headers` object when a new Request is created without headers. This causes a build error when running `astro build` to build a static page (`prerender = true`). The error message reads: ``` Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object> ``` The error occurs in [`astro/dist/core/request.js`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/request.ts), when trying to add a getter to `request.headers` which already has a value, leading to a conflict. **To Reproduce** To reproduce the issue, please refer to the following repository which demonstrates the error: https://github.com/avanderbergh/better-auth-astro-issue Steps for understanding the behavior: 1. Import any plugin from `better-auth/plugins` in an Astro middleware (`middleware.ts`). ```ts import { defineMiddleware } from "astro:middleware"; import "better-auth/plugins"; console.log(new Request("https://example.com").headers); // Logs as `Headers { map: {} }` ``` 2. Use the Cloudflare adapter (`@astrojs/cloudflare`). 3. Run `astro build` with `export const prerender = true` on a page. 4. Observe the build error: ``` Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object> ``` **Expected behavior** The build should complete successfully without modifying the `Request` prototype and without causing errors related to property descriptors. **Screenshots** N/A **Additional context** - The error is specific to the `@astrojs/cloudflare` adapter. - The suspected cause is a side-effect from `better-auth` plugins, which rely on `better-fetch` to replace the `fetch` function. - A repository that reproduces the issue is available here: https://github.com/avanderbergh/better-auth-astro-issue. - I have also opened an [issue](https://github.com/withastro/astro/issues/12548) on Astro to handle this more gracefully instead of breaking the build.
Author
Owner

@avanderbergh commented on GitHub (Nov 28, 2024):

Workaround
A workaround for this issue is to dynamically import the better-auth/plugins only if the page is not prerendered. This avoids the side-effect of modifying the Request prototype during build time.

Here is an updated example snippet that conditionally imports the necessary modules only when the page is not prerendered:

middleware.ts

import { defineMiddleware } from "astro:middleware";

export const onRequest = defineMiddleware(async ({ isPrerendered }, next) => {
  if (isPrerendered) return next();

  // Dynamically import the plugins to avoid issues during prerendering
  const { magicLink } = await import("better-auth/plugins");

  // ... additional logic for setting up authentication

  return next();
});

This ensures that the better-auth/plugins library (or similar libraries) are only imported when required, preventing build-time issues related to modifying Request.headers.

@avanderbergh commented on GitHub (Nov 28, 2024): **Workaround** A workaround for this issue is to dynamically import the `better-auth/plugins` only if the page is not prerendered. This avoids the side-effect of modifying the `Request` prototype during build time. Here is an updated example snippet that conditionally imports the necessary modules only when the page is not prerendered: middleware.ts ```ts import { defineMiddleware } from "astro:middleware"; export const onRequest = defineMiddleware(async ({ isPrerendered }, next) => { if (isPrerendered) return next(); // Dynamically import the plugins to avoid issues during prerendering const { magicLink } = await import("better-auth/plugins"); // ... additional logic for setting up authentication return next(); }); ``` This ensures that the `better-auth/plugins` library (or similar libraries) are only imported when required, preventing build-time issues related to modifying `Request.headers`.
Author
Owner

@Bekacru commented on GitHub (Nov 29, 2024):

Hey, thanks for taking the time to make a reproducible example. Out of curiosity, I saw you opened a PR on Astro—does this still require changes on our side?

@Bekacru commented on GitHub (Nov 29, 2024): Hey, thanks for taking the time to make a reproducible example. Out of curiosity, I saw you opened a PR on Astro—does this still require changes on our side?
Author
Owner

@avanderbergh commented on GitHub (Nov 29, 2024):

Sure, no problem!

Yes the PR on Astro will fix this specific issue.

I'm just wondering if in the future having this side effect might not cause other bugs? 🤔

@avanderbergh commented on GitHub (Nov 29, 2024): Sure, no problem! Yes the PR on Astro will fix this specific issue. I'm just wondering if in the future having this side effect might not cause other bugs? 🤔
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#293