Issue with sign up using express

Hi, I have been running in to an issue where my express server returns 422 Unprocessable Entity any time the client sends a sign up request. I have included my prisma schema, better auth config and my index.ts file (I have pretty much copied exactly whats on the better auth docs). Looking at the incoming requests on the express server, I can see the sign up requests come through however I noticed that the request body was undefined. Looking at the actual request through the network I can see that body is included in the post request. I have no issues adding data to the db manually through psql. Any ideas on what is causing this issue? auth.ts
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { prisma } from "../prisma/client";

export const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: "postgresql",
}),
emailAndPassword: {
enabled: true,
},
session: {
cookieCache: {
enabled: true,
maxAge: 5 * 60,
},
},
});
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { prisma } from "../prisma/client";

export const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: "postgresql",
}),
emailAndPassword: {
enabled: true,
},
session: {
cookieCache: {
enabled: true,
maxAge: 5 * 60,
},
},
});
index.ts
import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import { toNodeHandler } from "better-auth/node";
import { auth } from "./utils/auth";

dotenv.config();

const app = express();
const port = process.env.PORT || 3005;

app.use((req, res, next) => {
console.log("--- Incoming Request ---");
console.log("Request URL:", req.url);
console.log("Request IP:", req.ip);
console.log("Request Body:", req.body);
console.log("------------------------");
next();
});

app.use(
cors({
origin: "http://localhost:1420",
methods: ["GET", "POST", "PUT", "OPTIONS"],
credentials: true,
}),
);

app.all("/api/auth/*splat", toNodeHandler(auth));

app.use(express.json());

app.listen(port, () => {
console.log(`app listening on port ${port}`);
});
import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import { toNodeHandler } from "better-auth/node";
import { auth } from "./utils/auth";

dotenv.config();

const app = express();
const port = process.env.PORT || 3005;

app.use((req, res, next) => {
console.log("--- Incoming Request ---");
console.log("Request URL:", req.url);
console.log("Request IP:", req.ip);
console.log("Request Body:", req.body);
console.log("------------------------");
next();
});

app.use(
cors({
origin: "http://localhost:1420",
methods: ["GET", "POST", "PUT", "OPTIONS"],
credentials: true,
}),
);

app.all("/api/auth/*splat", toNodeHandler(auth));

app.use(express.json());

app.listen(port, () => {
console.log(`app listening on port ${port}`);
});
4 Replies
2ram
2ramOP7d ago
prima.schema
generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

model User {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
email String @unique
name String
emailVerified Boolean @default(false)
image String?
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
sessions Session[]
accounts Account[]

@@map("user")
}

model Session {
id String @id
expiresAt DateTime
token String
createdAt DateTime
updatedAt DateTime
ipAddress String?
userAgent String?
userId String @db.Uuid
user User @relation(fields: [userId], references: [id], onDelete: Cascade)

@@unique([token])
@@map("session")
}

model Account {
id String @id
accountId String
providerId String
userId String @db.Uuid
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
accessToken String?
refreshToken String?
idToken String?
accessTokenExpiresAt DateTime?
refreshTokenExpiresAt DateTime?
scope String?
password String?
createdAt DateTime
updatedAt DateTime

@@map("account")
}

model Verification {
id String @id
identifier String
value String
expiresAt DateTime
createdAt DateTime?
updatedAt DateTime?

@@map("verification")
}
generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

model User {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
email String @unique
name String
emailVerified Boolean @default(false)
image String?
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
sessions Session[]
accounts Account[]

@@map("user")
}

model Session {
id String @id
expiresAt DateTime
token String
createdAt DateTime
updatedAt DateTime
ipAddress String?
userAgent String?
userId String @db.Uuid
user User @relation(fields: [userId], references: [id], onDelete: Cascade)

@@unique([token])
@@map("session")
}

model Account {
id String @id
accountId String
providerId String
userId String @db.Uuid
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
accessToken String?
refreshToken String?
idToken String?
accessTokenExpiresAt DateTime?
refreshTokenExpiresAt DateTime?
scope String?
password String?
createdAt DateTime
updatedAt DateTime

@@map("account")
}

model Verification {
id String @id
identifier String
value String
expiresAt DateTime
createdAt DateTime?
updatedAt DateTime?

@@map("verification")
}
I followed the core schema provided here: https://www.better-auth.com/docs/concepts/database#account
KiNFiSH
KiNFiSH6d ago
can you please add body parser right after the initialization
app.use(express.json());
app.use(express.json());
2ram
2ramOP6d ago
@KiNFiSH I tried this, it allows for the request to finally go through but then the client side gets stuck on pending. Looking at the docs it says
Don’t use express.json() before the Better Auth handler. Use it only for other routes, or the client API will get stuck on "pending".
Don’t use express.json() before the Better Auth handler. Use it only for other routes, or the client API will get stuck on "pending".
Because of this I don't think this is the correct solution link to the docs where this is said: https://www.better-auth.com/docs/integrations/express
KiNFiSH
KiNFiSH6d ago
I mean the better auth route initialization You can put it right below it did you catch the body on the middleware ? and can u show me the serevr log on doing so

Did you find this page helpful?