Magic Link not working with InstantDB (better-auth-instantdb)

Hi! Thanks for this library. I've ran into an issue with Magic Link functionality. The magic link is being sent to my mail, but the verification process is not working. The $users are not created when using a magic link. I do see that "users are being created", but maybe this magicLink plugin is not working well with instantDB. SERVER_ERROR: Error: $users entity not found: a03a0d5f-335f-46e1-878c-4e4d1f880106
6 Replies
RadiantFrog
RadiantFrogOP•3mo ago
Here is my auth.ts
export const auth = betterAuth({
appName: APP_NAME,
secret: envVariables.BETTER_AUTH_SECRET,
baseURL: import.meta.env.VITE_BASE_URL || "http://localhost:3000",
database: instantDBAdapter({
db: instantServerDB,
usePlural: true, // Our schema uses plural form
debugLogs: true, // Enable debug logs to trace issues
}),
trustedOrigins: [
"http://localhost:3000",
"http://localhost:3001",
"https://moneymouth.ai",
...(import.meta.env.VITE_BASE_URL ? [import.meta.env.VITE_BASE_URL] : []),
],
plugins: [
magicLink({
// Auto-create users when they use magic links
disableSignUp: false,
expiresIn: 60 * 60 * 24 * 365 * 100, // 100 years in seconds
sendMagicLink: async ({ email, token, url }, request) => {
console.log("🔗 Magic link handler started");
console.log("🔗 Email:", email);
console.log("🔗 Token:", token);
console.log("🔗 URL:", url);

// Send the ebook email with magic link
await sendEbookEmail({ email, token, url });

console.log("📧 Magic link email sent successfully to:", email);
},
}),
],
user: {
changeEmail: {
enabled: true,
},
deleteUser: {
enabled: true,
},
},
});
export const auth = betterAuth({
appName: APP_NAME,
secret: envVariables.BETTER_AUTH_SECRET,
baseURL: import.meta.env.VITE_BASE_URL || "http://localhost:3000",
database: instantDBAdapter({
db: instantServerDB,
usePlural: true, // Our schema uses plural form
debugLogs: true, // Enable debug logs to trace issues
}),
trustedOrigins: [
"http://localhost:3000",
"http://localhost:3001",
"https://moneymouth.ai",
...(import.meta.env.VITE_BASE_URL ? [import.meta.env.VITE_BASE_URL] : []),
],
plugins: [
magicLink({
// Auto-create users when they use magic links
disableSignUp: false,
expiresIn: 60 * 60 * 24 * 365 * 100, // 100 years in seconds
sendMagicLink: async ({ email, token, url }, request) => {
console.log("🔗 Magic link handler started");
console.log("🔗 Email:", email);
console.log("🔗 Token:", token);
console.log("🔗 URL:", url);

// Send the ebook email with magic link
await sendEbookEmail({ email, token, url });

console.log("📧 Magic link email sent successfully to:", email);
},
}),
],
user: {
changeEmail: {
enabled: true,
},
deleteUser: {
enabled: true,
},
},
});
cc @daveycodez
The error $users entity not found: d5ac689d-f713-4ddb-a666-7cb42c8adcb1 occurs when Better Auth tries to create a session after successfully verifying the magic link. Here's what's happening:
Magic link verification works - the user's emailVerified is successfully updated to true
Session creation fails - when trying to create a session, the adapter looks for a user in the $users entity, but can't find one with that ID
Root Cause
Looking at your schema, you have a dual entity system:
$users - InstantDB's system entity for authentication
users - Your application entity for user data
The issue is that when the @daveyplate/better-auth-instantdb adapter creates a session, it needs to reference the user ID, but there's a mismatch between which entity it's looking for the user in.
The error $users entity not found: d5ac689d-f713-4ddb-a666-7cb42c8adcb1 occurs when Better Auth tries to create a session after successfully verifying the magic link. Here's what's happening:
Magic link verification works - the user's emailVerified is successfully updated to true
Session creation fails - when trying to create a session, the adapter looks for a user in the $users entity, but can't find one with that ID
Root Cause
Looking at your schema, you have a dual entity system:
$users - InstantDB's system entity for authentication
users - Your application entity for user data
The issue is that when the @daveyplate/better-auth-instantdb adapter creates a session, it needs to reference the user ID, but there's a mismatch between which entity it's looking for the user in.
daveycodez
daveycodez•3mo ago
Hey I'll take a deeper look at this in a little bit I'm working on a Better Auth UI release rn
RadiantFrog
RadiantFrogOP•3mo ago
no problem! I just found a fix I had to manually create a $users object
const newUserId = id();

// Create new $users record
await instantServerDB.transact(
instantServerDB.tx.$users[newUserId].update({
email,
}),
);
const newUserId = id();

// Create new $users record
await instantServerDB.transact(
instantServerDB.tx.$users[newUserId].update({
email,
}),
);
daveycodez
daveycodez•3mo ago
The adapter should do this for you did you look into the adapter source?
RadiantFrog
RadiantFrogOP•3mo ago
No I didnt look into the src. Has it been tested with magic links?
daveycodez
daveycodez•3mo ago
It shouldn’t function any different for magic links vs normal sign ups It should create the $user for you in the adapter

Did you find this page helpful?