Stuck in Upgrade Loop (OJS 3.4.0.8 to 3.5.0.3): Persistent Database Errors with 'site' and 'notification_subscription_settings' tables

Describe the issue or problem
Hi everyone,

I am seeking urgent help regarding a failed upgrade of my OJS instance from version 3.4.0.8 to 3.5.0.3.

I initially attempted this upgrade back in December 2025, but it failed midway. Since then, my installation has been stuck in a “half-upgraded” state. Every time I try to run the upgrade script now, I encounter a series of conflicting database errors. When I resolve one, the next one appears, often pointing back to the same tables.

The specific errors I am rotating between are:

  1. Missing Column in site Table: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'redirect' in 'site' (SQL: alter table site modify redirect bigint null)

  2. Duplicate Column in site Table: SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name 'redirect_context_id' (SQL: alter table site rename column redirect to redirect_context_id)

  3. Missing Column in notification_subscription_settings: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'context' in 'notification_subscription_settings' (SQL: alter table notification_subscription_settings rename column context to context_id)


Subject: Stuck in Upgrade Loop (OJS 3.4.0.8 to 3.5.0.3): Persistent Database Errors with ‘site’ and ‘notification_subscription_settings’ tables

Post Body:

Hi everyone,

I am seeking urgent help regarding a failed upgrade of my OJS instance from version 3.4.0.8 to 3.5.0.3.

I initially attempted this upgrade back in December 2025, but it failed midway. Since then, my installation has been stuck in a “half-upgraded” state. Every time I try to run the upgrade script now, I encounter a series of conflicting database errors. When I resolve one, the next one appears, often pointing back to the same tables.

The specific errors I am rotating between are:

  1. Missing Column in site Table:
    SQLSTATE[42S22]: Column not found: 1054 Unknown column 'redirect' in 'site' (SQL: alter table site modify redirect bigint null)

  2. Duplicate Column in site Table:
    SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name 'redirect_context_id' (SQL: alter table site rename column redirect to redirect_context_id)

  3. Missing Column in notification_subscription_settings:
    SQLSTATE[42S22]: Column not found: 1054 Unknown column 'context' in 'notification_subscription_settings' (SQL: alter table notification_subscription_settings rename column context to context_id)

The Dilemma:
It seems the upgrade script expects the old schema (e.g., the redirect column) to exist so it can rename or modify it. However, because of the previous failed attempts, the database structure is inconsistent. I have tried manually adding/dropping these columns via phpMyAdmin to satisfy the script, but it leads to further errors (like Duplicate key on foreign keys in the filters table).

Unfortunately, I do not have a clean SQL backup from before the December attempt. I am trying to fix the current database state manually to allow the 3.5.0.3 files to complete the migration.

Questions:

  • Is there a specific SQL sequence to “reset” the site and notification_subscription_settings tables to a state that the 3.5.0.x migration script can recognize?

  • How can I bypass these column-level conflicts without breaking the data integrity for my journals

Any advice on how to get out of this loop would be greatly appreciated. Thank you!

1 Like

@shahin Didn’t your tried getting help on errors from ChatGPT?
I hope you can get the solution to implement but If you need some technical help contact further.

I’ve tried multiple times with ChatGPT, but I’m consistently running into the same problems and errors. That’s why I’m still looking for a solid solution to implement this correctly.

The core problem: The migration script is stuck in a loop. It looks for old columns to rename/modify, but because of previous failed attempts, those columns are either already renamed, missing, or duplicated.

Specific errors I keep getting:

  1. site table: It throws Column not found: redirect when trying to modify it, but then throws Duplicate column: redirect_context_id when it tries to rename it.

  2. notification_subscription_settings table: It can’t find the context column to rename it to context_id.

  3. filters table: There are Duplicate key or Foreign Key constraint errors preventing the script from proceeding.

What I need from you: I need you to manually inspect the current database schema and compare it with a fresh OJS 3.4.0.8 structure. Specifically:

  • Reset the site and notification_subscription_settings tables to their 3.4.0.8 state (ensuring the correct column names like redirect and context exist with proper data types).

  • Clean up any partial migration entries in the migrations table if necessary.

  • Fix any conflicting Foreign Key constraints in the filters table so the 3.5 upgrade script can run without stopping.

Hi @shahin,

Without having a proper backup you’ll have to understand exactly where the upgrade failed and restart from there.

DO NOT re-run the upgrade using a failed database unless you’re instructed to do it, otherwise you’re probably going to corrupt/lose data.

To resume the upgrade from where it stopped, you’ll have to take a look at the file dbscripts/xml/upgrade.xml, it has a list with all the migrations that will be executed.

You’ve got to remove from the list the ones which were executed properly and leave the rest…

The important thing here is to detect EXACTLY which upgrade failed, then you’ll have to open its related PHP file, understand which was the last command that was executed properly, then resume from there… If you have a log of the upgrade, it will save you some time.

Only after doing these fixes you should attempt to run the upgrade.php.

That will be a tough task if you don’t have technical skills, so I recommend you to look for a programmer instead of fixing by yourself.

Best,
Jonas Raoni

Hi Jonas,

Thank you for the clear warning and the roadmap for recovery. Since I don’t have a backup, I understand that re-running the upgrade now is dangerous.

I have decided to hire a professional programmer to handle this ‘manual resume’ of the upgrade as per your advice. To help my programmer work efficiently, could you please provide a bit more detail on the following:

  1. How can we identify the Exact Migration Step that failed if the terminal log was lost? Should we check the versions table or specific schema changes?

  2. Once the failed script is identified in dbscripts/xml/upgrade.xml, what is the best way to ‘resume’ it? Should we comment out the successful <migration ... /> tags in that XML file?

  3. Are there any specific SQL queries you recommend to verify if the OJS 3.5.0.3 schema is partially applied?

  1. The version just gets updated if the upgrade is completed. The programmer will have to do what we call a “binary search”:
    1. If there are 1000 migrations, he should open the one in the middle (500), check what it does, and understand if it was applied or not, if it’s not clear, he can get a nearby migration that does structural changes (like adding a new field), this type of thing should be clear to understand if it was executed or not…
      If the migration in middle wasn’t executed, then he will know that the interruption happened between the first and the 500th migration, then he can continue the process (next one will be the 250th).
      We don’t have so many migrations, but you got the idea…
  2. Yep, the programmer can comment/delete. Once you detect which migration failed, you’ll have to understand what exactly failed (follow the script and compare with the data at the database), perhaps 500 records out of 1000 were updated, then it will be needed to complete the job… Hopefully this process involves just one script, so it’s not a VERY BIG deal, but it’s needed some technical knowledge to not miss something…
  3. You can install a clean OJS 3.5, then compare its database with your one. Some small differences are acceptable (our fault), but main things should be exactly the same (presence and name of fields, types, indexes, etc)

Best,
Jonas Raoni