{"record":{"id":"7cd623e22e32a590","repo":"nextauthjs/next-auth","slug":"no-user-id-7cd623","errorCode":null,"errorMessage":"No user id.","messagePattern":"No user id\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/adapter-drizzle/src/lib/sqlite.ts","lineNumber":193,"sourceCode":"      const result =\n        (await client\n          .select({\n            session: sessionsTable,\n            user: usersTable,\n          })\n          .from(sessionsTable)\n          .where(eq(sessionsTable.sessionToken, sessionToken))\n          .innerJoin(usersTable, eq(usersTable.id, sessionsTable.userId))\n          .get()) ?? null\n\n      return result as Awaitable<{\n        session: AdapterSession\n        user: AdapterUser\n      } | null>\n    },\n    async updateUser(data: Partial<AdapterUser> & Pick<AdapterUser, \"id\">) {\n      if (!data.id) {\n        throw new Error(\"No user id.\")\n      }\n\n      const result = await client\n        .update(usersTable)\n        .set(data)\n        .where(eq(usersTable.id, data.id))\n        .returning()\n        .get()\n\n      if (!result) {\n        throw new Error(\"User not found.\")\n      }\n\n      return result as Awaitable<AdapterUser>\n    },\n    async updateSession(\n      data: Partial<AdapterSession> & Pick<AdapterSession, \"sessionToken\">\n    ) {","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/adapter-drizzle/src/lib/sqlite.ts#L175-L211","documentation":"Same guard as its PostgreSQL sibling but in the SQLite Drizzle adapter: updateUser requires a truthy id before it can build the WHERE clause. A missing id would make the UPDATE ambiguous or match all rows, so the adapter throws 'No user id.' immediately.","triggerScenarios":"Calling updateUser with an object lacking id, id: undefined, or id: '' — commonly from hand-built AdapterUser objects or a destructuring bug that drops the id field.","commonSituations":"SQLite dev setups where user rows are seeded manually without ids; custom sign-in flows that pass a partial user; renaming the primary key column in the Drizzle schema so data.id is no longer populated from DB results.","solutions":["Pass the id explicitly: updateUser({ id: user.id, ...changes }).","Log/inspect the user object right before the call to confirm id is present and truthy.","Make sure the user came from an adapter query (getUser, getUserByEmail) so id is set from the row.","Check the usersTable id column mapping and type in the Drizzle SQLite schema."],"exampleFix":"// before\nconst { id: _ignored, ...patch } = payload\nawait adapter.updateUser(patch)\n// after\nawait adapter.updateUser({ id: payload.id, ...payload.changes })","handlingStrategy":"validation","validationCode":"if (!user?.id) throw new Error('updateUser requires a valid user.id')\nawait adapter.updateUser({ id: user.id, ...patch })","typeGuard":"function hasUserId(u: unknown): u is AdapterUser {\n  return typeof u === 'object' && u !== null &&\n    typeof (u as AdapterUser).id === 'string' && (u as AdapterUser).id.length > 0\n}","tryCatchPattern":"try {\n  await adapter.updateUser(patch)\n} catch (e) {\n  if ((e as Error).message === 'No user id.') {\n    console.error('updateUser called without id; payload:', patch)\n    return\n  }\n  throw e\n}","preventionTips":["Never destructure-and-drop id from user payloads before updating.","Seed SQLite dev databases through the adapter (createUser) so ids follow the expected format.","Run a typecheck with a required-id payload type instead of loose Partial<AdapterUser>."],"tags":["input-validation","database","drizzle","sqlite"],"backgroundTag":"missing-entity-id","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}