[GH-ISSUE #9170] Sessions deleting themselves after upgrading to 1.5.0 - ON UPDATE Bug (SOLVED) #28616

Open
opened 2026-04-17 20:03:10 -05:00 by GiteaMirror · 0 comments
Owner

Originally created by @biegehydra on GitHub (Apr 14, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/9170

I'm putting this here for visibility so that if anyone encounters the same issue they may stumble upon this issue and save themselves the hours I just want through debugging this issue.

I had an issue after upgrading to 1.5.0 where after a user signed in, they were not getting a session. We'll, they were kind of getting a session. The login (with OTP) would succeed and they would get redirected to the home page (which requires being authenticated) and then they would get redirected back to login because they had no session.

What's weird is this only happened when I deployed to vercel. Locally, 1.5.0 worked fine. So I read through all the changelogs and assumed something was amuck with trusted origins, my hooks, or maybe my base url. But none of the configurations I tried would work. I tracked the issue down to this specific release: "v1.5.0-beta.17". Any release before it seemed to work fine. Why? I have no idea, in my eyes my setup never should have worked

The issue

For MySql/MariaDb, the first timestamp column in every table automagically gets:

  • DEFAULT CURRENT_TIMESTAMP
  • ON UPDATE CURRENT_TIMESTAMP

Which meant that when I ran the migration npx auth@latest generate, I unknowingly added ON UPDATE CURRENT_TIMESTAMP to multiple expiresAt fields. The issues I was seeing made sense now, something was updating the session, which triggered the expiresAt to be set to the current timestamp, which caused better-auth to detect that the session was expired and sign the user out and invalidate/remove their cookie.

The fix for me was just some alter statements to fix all the tables

ALTER TABLE `session` 
  MODIFY COLUMN `expiresAt` TIMESTAMP(3) NOT NULL;

I also globally set explicit_defaults_for_timestamp = 1 for my database which prevents this behavior.

What Better-Auth can do

Honestly, I am not sure. I'm no expert in mysql/mariadb. I would assume that if you just changed the migration code so that expiresAt appears after the other columns, it would help. Maybe it can even explicitly assign a default value or explicitly define on update to do nothing. I am not sure, I will leave that up to you guys.

create table `session` (
  `id` varchar(36) not null primary key, 
  `expiresAt` timestamp(3) not null, // first timestamp column
   ...other columns
);

create table `verification` (
  `id` varchar(36) not null primary key, 
  `identifier` varchar(255) not null, 
  `value` text not null, 
  `expiresAt` timestamp(3) not null,  // first timestamp column
  ...other columns
);
// same issue with invitation table and probably others
Originally created by @biegehydra on GitHub (Apr 14, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/9170 I'm putting this here for visibility so that if anyone encounters the same issue they may stumble upon this issue and save themselves the hours I just want through debugging this issue. I had an issue after upgrading to 1.5.0 where after a user signed in, they were not getting a session. We'll, they were kind of getting a session. The login (with OTP) would succeed and they would get redirected to the home page (which requires being authenticated) and then they would get redirected back to login because they had no session. What's weird is this only happened when I deployed to vercel. Locally, 1.5.0 worked fine. So I read through all the changelogs and assumed something was amuck with trusted origins, my hooks, or maybe my base url. But none of the configurations I tried would work. I tracked the issue down to this specific release: "v1.5.0-beta.17". Any release before it seemed to work fine. Why? I have no idea, in my eyes my setup never should have worked ## The issue For MySql/MariaDb, the first timestamp column in every table automagically gets: - DEFAULT CURRENT_TIMESTAMP - ON UPDATE CURRENT_TIMESTAMP Which meant that when I ran the migration `npx auth@latest generate`, I unknowingly added `ON UPDATE CURRENT_TIMESTAMP` to multiple `expiresAt` fields. The issues I was seeing made sense now, something was updating the session, which triggered the expiresAt to be set to the current timestamp, which caused better-auth to detect that the session was expired and sign the user out and invalidate/remove their cookie. The fix for me was just some alter statements to fix all the tables ```sql ALTER TABLE `session` MODIFY COLUMN `expiresAt` TIMESTAMP(3) NOT NULL; ``` I also globally set `explicit_defaults_for_timestamp = 1` for my database which prevents this behavior. ## What Better-Auth can do Honestly, I am not sure. I'm no expert in mysql/mariadb. I would assume that if you just changed the migration code so that expiresAt appears after the other columns, it would help. Maybe it can even explicitly assign a default value or explicitly define on update to do nothing. I am not sure, I will leave that up to you guys. ```sql create table `session` ( `id` varchar(36) not null primary key, `expiresAt` timestamp(3) not null, // first timestamp column ...other columns ); create table `verification` ( `id` varchar(36) not null primary key, `identifier` varchar(255) not null, `value` text not null, `expiresAt` timestamp(3) not null, // first timestamp column ...other columns ); // same issue with invitation table and probably others ```
GiteaMirror added the database label 2026-04-17 20:03:10 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#28616