nextauthjs/next-auth · error · Error
userId is undef in createSession
Error message
userId is undef in createSession
What it means
The Neon adapter's createSession guards that userId is defined before inserting into the sessions table, throwing a plain Error otherwise. It protects against writing a NULL 'userId' FK. Receiving undefined here means the caller passed a malformed AdapterSession without a userId.
Source
Thrown at packages/adapter-neon/src/index.ts:172
account.userId,
account.provider,
account.type,
account.providerAccountId,
account.access_token,
account.expires_at,
account.refresh_token,
account.id_token,
account.scope,
account.session_state,
account.token_type,
]
const result = await client.query(sql, params)
return result.rows[0]
},
async createSession({ sessionToken, userId, expires }) {
if (userId === undefined) {
throw Error(`userId is undef in createSession`)
}
const sql = `insert into sessions ("userId", expires, "sessionToken")
values ($1, $2, $3)
RETURNING id, "sessionToken", "userId", expires`
const result = await client.query(sql, [userId, expires, sessionToken])
return result.rows[0]
},
async getSessionAndUser(sessionToken: string | undefined): Promise<{
session: AdapterSession
user: AdapterUser
} | null> {
if (sessionToken === undefined) {
return null
}
const result1 = await client.query(
`select * from sessions where "sessionToken" = $1`,View on GitHub (pinned to a1a16a5a77)
Solutions
- Inspect where the session is created and ensure the user record exists with a defined id before createSession is called
- Verify your user-mapping function returns the adapter's AdapterUser shape ({ id, ... }) not a raw DB row with different column names
- Log the incoming arguments in a wrapper adapter to identify which flow passes userId: undefined
- If you have a custom user provider/adapter, confirm createUser returns the inserted row
Example fix
// before
await adapter.createSession({ sessionToken, userId: user.id, expires }) // user.id undefined
// after
if (!user?.id) throw new Error(`Cannot create session: user not persisted (id missing)`)
await adapter.createSession({ sessionToken, userId: user.id, expires }) Defensive patterns
Strategy: type-guard
Validate before calling
if (session?.userId === undefined) throw new Error('createSession requires a persisted user id') Type guard
function hasUserId(s: { userId?: unknown }): s is { userId: string } {
return typeof s.userId === 'string' && s.userId.length > 0
} Try / catch
try {
await adapter.createSession({ sessionToken, userId, expires })
} catch (e) {
if (e instanceof Error && e.message === 'userId is undef in createSession') {
throw new Error('User was not persisted before session creation', { cause: e })
}
throw e
} Prevention
- Always createUser before createSession in custom flows
- Map DB rows to AdapterUser with an explicit id field
- Add adapter-level unit tests for the database session strategy
- Use database-session strategy only when user binding is guaranteed
When it happens
Trigger: Calling adapter.createSession({ sessionToken, userId: undefined, expires }) — typically from a session callback/DB session flow where the user row (and thus user.id) was undefined or the createUserServiceUser step silently failed.
Common situations: Custom code constructing session objects manually; a user create step returning undefined (e.g. mapping mismatch in a custom adapter chain); JWT/strategy misconfiguration where sessions are created without a bound user; upstream user id field named differently (e.g. user_id) so id is undefined.
Related errors
- userId is undef in createSession
- Couldn't create session
- [createSession] Failed to fetch created session
- WebAuthn authenticator not found in database: ${JSON.stringi
- Failed to update authenticator counter. This may cause futur
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/3c70af96a465d7b3.
Report an issue: GitHub.