How can I access `env.DB` in my Pages/Worker on production?

Steps to reproduce: 1. Clone https://github.com/cjxe/nextjs-d1-drizzle-cloudflare-pages 2. Follow README.md. 3. Run pnpm start or pnpm pages:prod. 4. Launch the web app using your favourite browser. Error:
[Error: Failed to retrieve the Cloudflare request context.]
[Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.] {
digest: '3614312654'
}
[Error: Failed to retrieve the Cloudflare request context.]
[Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.] {
digest: '3614312654'
}
I don't get this error when I run on dev due to how next.config.mjs is set up, but I can't make this work on production. The main issue is the Cloudflare pages return an error when it tries running getRequestContext().env.DB in src/server/db/index.ts.
GitHub
GitHub - cjxe/nextjs-d1-drizzle-cloudflare-pages
Contribute to cjxe/nextjs-d1-drizzle-cloudflare-pages development by creating an account on GitHub.
29 Replies
laurent
laurent•12mo ago
src/db/

import * as schema from "@/db/schema/schema";
import { getRequestContext } from "@cloudflare>/next-on-pages";
import { drizzle } from "drizzle-orm/d1";
export const runtime = "edge";

function getDB() {
if (process.env.NODE_ENV === "development") {
const { env } = getRequestContext();
//@ts-ignore
return drizzle(env.DB, { schema });
}
// Production
//@ts-ignore
return drizzle(process.env.DB, { schema });
}

export const db = getDB();
src/db/

import * as schema from "@/db/schema/schema";
import { getRequestContext } from "@cloudflare>/next-on-pages";
import { drizzle } from "drizzle-orm/d1";
export const runtime = "edge";

function getDB() {
if (process.env.NODE_ENV === "development") {
const { env } = getRequestContext();
//@ts-ignore
return drizzle(env.DB, { schema });
}
// Production
//@ts-ignore
return drizzle(process.env.DB, { schema });
}

export const db = getDB();
wrangler.toml

[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "prod-dbname"
database_id = "123



[[env.production.d1_databases]]
database_id = "123"
binding = "DB"
database_name = "DB"
wrangler.toml

[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "prod-dbname"
database_id = "123



[[env.production.d1_databases]]
database_id = "123"
binding = "DB"
database_name = "DB"
Baran
BaranOP•12mo ago
Thanks for the reply! I made your suggested changes, and the terminal threw this error: TypeError: Cannot read properties of undefined (reading 'prepare') šŸ˜µā€šŸ’«
laurent
laurent•12mo ago
what's calling the database? how is it imported?
Baran
BaranOP•12mo ago
laurent
laurent•12mo ago
can you try a simple api route like that? the db is the one exported above
import { db } from "@/db/drizzleDB";
import { cities } from "@/db/schema/schema";
import type { NextRequest } from "next/server";

export const runtime = "edge";

export async function GET(request: NextRequest) {

const result = await db.select().from(cities);

return Response.json({ result });
}
import { db } from "@/db/drizzleDB";
import { cities } from "@/db/schema/schema";
import type { NextRequest } from "next/server";

export const runtime = "edge";

export async function GET(request: NextRequest) {

const result = await db.select().from(cities);

return Response.json({ result });
}
Baran
BaranOP•12mo ago
sure, 2 secs how would you like me to fetch in the front end, navigate to the endpoint in the browser?
laurent
laurent•12mo ago
to test the api route you use something like postman and call GET localhost:3000/api/something I use thunder client in vscode
Baran
BaranOP•12mo ago
No description
Baran
BaranOP•12mo ago
i am getting the same error both thunder client and my browser returned the same
laurent
laurent•12mo ago
are you exporting the db object as I showed you?
Baran
BaranOP•12mo ago
i mean the server returned the sam error, the browser and thunder client returned "500 internal server error"
Baran
BaranOP•12mo ago
No description
laurent
laurent•12mo ago
did you double check your wrangler.toml values for the db?
Baran
BaranOP•12mo ago
i am shaking
[[d1_databases]] # <-- i had to rename this from `env.production.d1_databases` to `d1_databases`
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "TBA" # When you create your D1 DB, you choose the name
database_id = "TBA"
preview_database_id = "DB"
[[d1_databases]] # <-- i had to rename this from `env.production.d1_databases` to `d1_databases`
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "TBA" # When you create your D1 DB, you choose the name
database_id = "TBA"
preview_database_id = "DB"
thank you very much
laurent
laurent•12mo ago
do you see a database there?
No description
Baran
BaranOP•12mo ago
i even got the api response
Baran
BaranOP•12mo ago
No description
Baran
BaranOP•12mo ago
No description
laurent
laurent•12mo ago
ah ok good!
Baran
BaranOP•12mo ago
whats your wrangler command to connect to the production database?
laurent
laurent•12mo ago
I copied it above
Baran
BaranOP•12mo ago
oh i meant something like
pnpm wrangler pages dev --env production .vercel/output/static
pnpm wrangler pages dev --env production .vercel/output/static
laurent
laurent•12mo ago
I don't think you can
No description
Baran
BaranOP•12mo ago
hm, thats a shame
Coolio85
Coolio85•12mo ago
This might sound simple, but did you update these values for the d1 database you want to bind?
Baran
BaranOP•12mo ago
yeah that's my template and i was trying to find what was wrong with it, but thanks for checking in
Coolio85
Coolio85•12mo ago
šŸ‘ only saying because I've definitely not done that before :hide_the_pain: :laughingpepe: One thing I can suggest, is try getting rid of the conditional regarding process.env.NODE_ENV, my nextjs pages project looks similar to this
import { getRequestContext } from "@cloudflare/next-on-pages"
import { PrismaClient } from '@prisma/client'
import { PrismaD1 } from '@prisma/adapter-d1'

const getDb = (): PrismaClient => {
const binding = getRequestContext().env.DB;

const adapter = new PrismaD1(binding)
const prisma = new PrismaClient({ adapter })

return prisma;
}

export default getDb;
import { getRequestContext } from "@cloudflare/next-on-pages"
import { PrismaClient } from '@prisma/client'
import { PrismaD1 } from '@prisma/adapter-d1'

const getDb = (): PrismaClient => {
const binding = getRequestContext().env.DB;

const adapter = new PrismaD1(binding)
const prisma = new PrismaClient({ adapter })

return prisma;
}

export default getDb;
With a wrangler file of
[[d1_databases]]
binding = "DB"
database_name = "name"
database_id = "[ID]"
preview_database_id = "[ID]"

[[env.preview.d1_databases]]
binding = "DB"
database_name = "name"
database_id = "[ID]"
preview_database_id = "[ID]"
[[d1_databases]]
binding = "DB"
database_name = "name"
database_id = "[ID]"
preview_database_id = "[ID]"

[[env.preview.d1_databases]]
binding = "DB"
database_name = "name"
database_id = "[ID]"
preview_database_id = "[ID]"
Baran
BaranOP•12mo ago
i tried it, and for some reason @cloudflare/next-on-pages throws an error, so I left the conditione unrelated to this thread, but did you manage to view the preview or prod database using drizzle-kit studio?
// drizzle.config.ts
import { env } from '@/env';

/*
* NOTE: Workaround to make drizzle studio work with D1.
* https://kevinkipp.com/blog/going-full-stack-on-astro-with-cloudflare-d1-and-drizzle/
* Github discussion: https://github.com/drizzle-team/drizzle-orm/discussions/1545#discussioncomment-8115423
*/
export default env.LOCAL_DB_PATH
? { // i can see the local database
schema: './src/server/db/schema.ts',
driver: 'd1',
dialect: 'sqlite',
dbCredentials: {
url: env.LOCAL_DB_PATH,
},
}
: { // i can't see the db on d1
schema: './src/server/db/schema.ts',
out: './migrations',
driver: 'd1',
dbCredentials: {
wranglerConfigPath:
new URL('wrangler.toml', import.meta.url).pathname + env.WRANGLER_CONFIG
? ` ${env.WRANGLER_CONFIG}`
: '',
dbName: env.DB_NAME!,
},
};
// drizzle.config.ts
import { env } from '@/env';

/*
* NOTE: Workaround to make drizzle studio work with D1.
* https://kevinkipp.com/blog/going-full-stack-on-astro-with-cloudflare-d1-and-drizzle/
* Github discussion: https://github.com/drizzle-team/drizzle-orm/discussions/1545#discussioncomment-8115423
*/
export default env.LOCAL_DB_PATH
? { // i can see the local database
schema: './src/server/db/schema.ts',
driver: 'd1',
dialect: 'sqlite',
dbCredentials: {
url: env.LOCAL_DB_PATH,
},
}
: { // i can't see the db on d1
schema: './src/server/db/schema.ts',
out: './migrations',
driver: 'd1',
dbCredentials: {
wranglerConfigPath:
new URL('wrangler.toml', import.meta.url).pathname + env.WRANGLER_CONFIG
? ` ${env.WRANGLER_CONFIG}`
: '',
dbName: env.DB_NAME!,
},
};
UPDATE: the issue is fixed with drizzle-kit v0.21.3, THANK YOU! ā¤ļø

Did you find this page helpful?