MongoDB E11000 Duplicate "id" Key Error

I've been encountering this issue since I'm using Discord's OAUTH2 with BetterAuth while using MongoDB as an adapter. The exact error is as shown:
ERROR [Better Auth]: MongoServerError: E11000 duplicate key error collection: credmaid.webusers index: id_1 dup key: { id: null }
ERROR [Better Auth]: MongoServerError: E11000 duplicate key error collection: credmaid.webusers index: id_1 dup key: { id: null }
I've tried setting generateId to false like:
advanced: {
database: {
generateId: false,
},
cookiePrefix: "credmaid",
},
advanced: {
database: {
generateId: false,
},
cookiePrefix: "credmaid",
},
What could be the issue?
Solution:
it could be that there are already fields in that webusers table with the id field & it's unique constraint, so even after you updated the mongoose schema it doesn't reflect mongo
Jump to solution
21 Replies
Ping
Ping3h ago
can I see your full auth config?
Yue
YueOP3h ago
Thanks for the quick reply! Here's the full auth config, hope I didn't miss anything! I split it into two since I don't have nitro
const client = new MongoClient(MONGODB_URI);
const db = client.db(MONGODB_NAME);
const client = new MongoClient(MONGODB_URI);
const db = client.db(MONGODB_NAME);
export const auth = betterAuth({
database: mongodbAdapter(db),
plugins: [
adminPlugin({
ac,
roles: {
admin,
user,
},
}),
sveltekitCookies(getRequestEvent),
],
session: {
expiresIn: 60 * 60 * 24 * 7,
updateAge: 60 * 60 * 24,
additionalFields: {
impersonatedBy: {
type: "string",
fieldName: "impersonatedBy",
required: false,
},
},
},
advanced: {
database: {
generateId: false,
},
cookiePrefix: "maximclient",
},
user: {
modelName: "webusers",
additionalFields: {
discordId: {
type: "string",
fieldName: "discordId",
required: true,
},
role: {
type: "string",
fieldName: "role",
required: false,
},
banned: {
type: "boolean",
fieldName: "banned",
required: false,
},
banReason: {
type: "string",
fieldName: "banReason",
required: false,
},
banExpires: {
type: "date",
fieldName: "banExpires",
required: false,
},
},
fields: {
discordId: "discordId",
email: "email",
emailVerified: "emailVerified",
image: "image",
createdAt: "createdAt",
updatedAt: "updatedAt",
},
},
socialProviders: {
discord: {
enabled: true,
disableDefaultScope: true,
scope: ["identify", "guilds", "guilds.members.read"],
mapProfileToUser: async (profile) => {
return {
discordId: profile.id,
email:
profile.email && profile.email !== "" ? profile.email : uuidv4(),
emailVerified: profile.verified as boolean,
};
},
clientId: DISCORD_CLIENT_ID as string,
clientSecret: DISCORD_CLIENT_SECRET as string,
},
},
});
export const auth = betterAuth({
database: mongodbAdapter(db),
plugins: [
adminPlugin({
ac,
roles: {
admin,
user,
},
}),
sveltekitCookies(getRequestEvent),
],
session: {
expiresIn: 60 * 60 * 24 * 7,
updateAge: 60 * 60 * 24,
additionalFields: {
impersonatedBy: {
type: "string",
fieldName: "impersonatedBy",
required: false,
},
},
},
advanced: {
database: {
generateId: false,
},
cookiePrefix: "maximclient",
},
user: {
modelName: "webusers",
additionalFields: {
discordId: {
type: "string",
fieldName: "discordId",
required: true,
},
role: {
type: "string",
fieldName: "role",
required: false,
},
banned: {
type: "boolean",
fieldName: "banned",
required: false,
},
banReason: {
type: "string",
fieldName: "banReason",
required: false,
},
banExpires: {
type: "date",
fieldName: "banExpires",
required: false,
},
},
fields: {
discordId: "discordId",
email: "email",
emailVerified: "emailVerified",
image: "image",
createdAt: "createdAt",
updatedAt: "updatedAt",
},
},
socialProviders: {
discord: {
enabled: true,
disableDefaultScope: true,
scope: ["identify", "guilds", "guilds.members.read"],
mapProfileToUser: async (profile) => {
return {
discordId: profile.id,
email:
profile.email && profile.email !== "" ? profile.email : uuidv4(),
emailVerified: profile.verified as boolean,
};
},
clientId: DISCORD_CLIENT_ID as string,
clientSecret: DISCORD_CLIENT_SECRET as string,
},
},
});
Ping
Ping2h ago
when you use generateId: false, it's expected that your DB will generate the ID Is that intentional for you?
Yue
YueOP2h ago
I don't really understand, I had presumed that it uses the _id field which mongodb automatically generates. Could you explain what you mean?
Ping
Ping1h ago
you shouldn't need to use generateId: false, better-auth handles id generation automatically if you commented out your code for mapProfileToUser does everything work?
Yue
YueOP1h ago
I just tried it and commented out generateId and mapProfileToUser, I used two accounts to test this: Account 1 (email is available): The account registers successfully, however id field is not set in the collection:
{
"_id": {
"$oid": "69006cf3523576b1036b7e6b"
},
"name": "Yue",
"email": "**********@gmail.com", // I censored this
"emailVerified": true,
"image": "https://cdn.discordapp.com/avatars/347339395415670784/ff1548ebbba86c2b2379fb0da218d818.png",
"createdAt": {
"$date": "2025-10-28T07:12:51.445Z"
},
"updatedAt": {
"$date": "2025-10-28T07:12:51.445Z"
},
"role": "user"
}
{
"_id": {
"$oid": "69006cf3523576b1036b7e6b"
},
"name": "Yue",
"email": "**********@gmail.com", // I censored this
"emailVerified": true,
"image": "https://cdn.discordapp.com/avatars/347339395415670784/ff1548ebbba86c2b2379fb0da218d818.png",
"createdAt": {
"$date": "2025-10-28T07:12:51.445Z"
},
"updatedAt": {
"$date": "2025-10-28T07:12:51.445Z"
},
"role": "user"
}
Account 2 (Email is empty) It throws the error: [Better Auth]: Provider did not return email. This could be due to misconfiguration in the provider settings. A temporary workaround I did for this was using the mapProfileToUser method
Ping
Ping1h ago
id field is not set in the collection
Hmm, yeah BA tries to use _id for ids in mongo
A temporary workaround I did for this was using the mapProfileToUser method
I see so if you remove the generate id code entirely, and just keep the mapProfileToUser you then run into errors saying id is null or something?
Yue
YueOP1h ago
I just ran the code like you said, removing the generateId field and restoring the mapProfileToUser method and it throws the original error:
2025-10-28T07:24:13.657Z ERROR [Better Auth]: MongoServerError: E11000 duplicate key error collection: maximclient.webusers index: id_1 dup key: { id: null }
2025-10-28T07:24:13.658Z ERROR [Better Auth]: unable_to_create_user
2025-10-28T07:24:13.657Z ERROR [Better Auth]: MongoServerError: E11000 duplicate key error collection: maximclient.webusers index: id_1 dup key: { id: null }
2025-10-28T07:24:13.658Z ERROR [Better Auth]: unable_to_create_user
Ping
Ping1h ago
did you index or change any of the schema for mongo?
Yue
YueOP1h ago
I assume you mean the schema for the WebUser collection, I do have it set, am I supposed to? Here's my WebUser schema:
import mongoose, { Document, Model, Schema } from "mongoose";

export interface WebUser extends Document {
id: string;
name: string;
email: string;
discordId: string;
emailVerified: boolean;
image: string;
createdAt: Date;
updatedAt: Date;
}

const WebUserSchema: Schema<WebUser> = new Schema({
id: { type: String, required: true, unique: true },
name: { type: String, required: true },
email: { type: String, required: true },
discordId: { type: String, required: true },
emailVerified: { type: Boolean, required: true },
image: { type: String, required: false },
createdAt: { type: Date, required: true },
updatedAt: { type: Date, required: true },
});

const WebUserModel: Model<WebUser> =
mongoose.models.WebUser || mongoose.model<WebUser>("Webuser", WebUserSchema);

export default WebUserModel;
import mongoose, { Document, Model, Schema } from "mongoose";

export interface WebUser extends Document {
id: string;
name: string;
email: string;
discordId: string;
emailVerified: boolean;
image: string;
createdAt: Date;
updatedAt: Date;
}

const WebUserSchema: Schema<WebUser> = new Schema({
id: { type: String, required: true, unique: true },
name: { type: String, required: true },
email: { type: String, required: true },
discordId: { type: String, required: true },
emailVerified: { type: Boolean, required: true },
image: { type: String, required: false },
createdAt: { type: Date, required: true },
updatedAt: { type: Date, required: true },
});

const WebUserModel: Model<WebUser> =
mongoose.models.WebUser || mongoose.model<WebUser>("Webuser", WebUserSchema);

export default WebUserModel;
Ping
Ping1h ago
we don't use id, we use _id like normal mongo tables likely the reason for the error
Yue
YueOP1h ago
Okay, I'll try changing it I assume I just change it in the schema from id to _id, right?
Ping
Ping1h ago
yeah, try that normally we don't have schemas for mongo, we don't officially support mongoose technically so not sure how this will go
Yue
YueOP1h ago
I've changed the schema to:
const WebUserSchema: Schema<WebUser> = new Schema({
_id: { type: String, required: true, unique: true },
name: { type: String, required: true },
email: { type: String, required: true },
discordId: { type: String, required: true },
emailVerified: { type: Boolean, required: true },
image: { type: String, required: false },
createdAt: { type: Date, required: true },
updatedAt: { type: Date, required: true },
});
const WebUserSchema: Schema<WebUser> = new Schema({
_id: { type: String, required: true, unique: true },
name: { type: String, required: true },
email: { type: String, required: true },
discordId: { type: String, required: true },
emailVerified: { type: Boolean, required: true },
image: { type: String, required: false },
createdAt: { type: Date, required: true },
updatedAt: { type: Date, required: true },
});
And it indeed throws the same error still: MongoServerError: E11000 duplicate key error collection: maximclient.webusers index: id_1 dup key: { id: null } I'm out of ideas, if it's as you say, I think the issue might really be because I'm using mongoose, so maybe if I switched to the official mongodb package, it may work
Ping
Ping1h ago
are you passing normal mongo client to the better-auth adapter? or mongoose
Yue
YueOP1h ago
import { MongoClient } from "mongodb";
import { mongodbAdapter } from "better-auth/adapters/mongodb";
import { ac, admin, user } from "$lib/auth/permissions";
import { admin as adminPlugin } from "better-auth/plugins";
import { v4 as uuidv4 } from "uuid";

const client = new MongoClient(MONGODB_URI);
const db = client.db(MONGODB_NAME);

export const auth = betterAuth({
// ... your config
database: mongodbAdapter(db),
import { MongoClient } from "mongodb";
import { mongodbAdapter } from "better-auth/adapters/mongodb";
import { ac, admin, user } from "$lib/auth/permissions";
import { admin as adminPlugin } from "better-auth/plugins";
import { v4 as uuidv4 } from "uuid";

const client = new MongoClient(MONGODB_URI);
const db = client.db(MONGODB_NAME);

export const auth = betterAuth({
// ... your config
database: mongodbAdapter(db),
Yes, I'm passing the client from mongodb And accessing the database using mongoose when it comes to using it outside of better-auth
Ping
Ping1h ago
Ah that should be fine then
Solution
Ping
Ping1h ago
it could be that there are already fields in that webusers table with the id field & it's unique constraint, so even after you updated the mongoose schema it doesn't reflect mongo
Ping
Ping1h ago
could it be possible to just reset that table?
Yue
YueOP1h ago
I'll give it a try Omg. It works like a charm. Thank you! I appreciate it a lot, that really was the issue!
Ping
Ping1h ago
awesome, nice

Did you find this page helpful?