Fixing Failed Upgrades: php tools/upgrade.php CLI Debugging
Step-by-step diagnostic manual for troubleshooting failed OJS upgrades. Learn how to read PHP stack traces, fix foreign key constraint violations, and resume migrations.
Real Problem
When an OJS CLI upgrade fails halfway through, system administrators often panic and attempt to re-run the upgrade command without rolling back, compounding database corruption.
Practical Solution
Enable verbose error logging in config.inc.php, identify the exact failing migration step, roll back to your pre-upgrade database snapshot, apply targeted SQL schema patches, and re-execute the migration cleanly.
The Golden Rule of Failed Upgrade Recovery
When an Open Journal Systems upgrade fails, the most dangerous reaction is to immediately re-run the upgrade command.
OJS migration scripts are designed to execute sequentially on a known baseline schema state. Once an upgrade encounters a fatal exception halfway through, some tables have been dropped, others have been created, and column definitions have been modified. Re-running the script against this hybrid state will invariably crash on "Table already exists" or "Duplicate column name" errors.
Rule #1: Always drop the failed database and restore your clean pre-upgrade snapshot before attempting a revised run.
Enabling Diagnostic Stack Traces in config.inc.php
To understand why the upgrade halted, you must force OJS to provide detailed debugging output. Open config.inc.php and adjust the [debug] section:
[debug]
show_stacktrace = On
display_errors = On
deprecation_warnings = Off
Now execute the upgrade from the command line while redirecting both standard output and error streams to a log file:
php tools/upgrade.php upgrade 2>&1 | tee upgrade_debug.log
Diagnosing Common Fatal Upgrade Errors
Error 1: Foreign Key Constraint Violation (Error 1452 / 1215)
Occurs when the migration script attempts to add a foreign key constraint (e.g., between publication_settings and publications), but the child table contains orphaned rows with IDs that do not exist in the parent table.
Fix: Restore snapshot, run SQL queries to find and delete orphaned records in child tables, then re-execute the upgrade.
Error 2: Duplicate Entry for Key in *_settings Tables
Occurs when localized settings (e.g., submission_settings or journal_settings) contain multiple rows with identical (id, locale, setting_name) tuples.
Fix: Restore snapshot, run a GROUP BY ... HAVING COUNT(*) > 1 query to isolate and delete duplicate rows, retaining the row with the most recent timestamp.
Error 3: PHP Memory Exhaustion Fatal Error
Occurs when large metrics or log tables exceed the memory_limit during serialization.
Fix: Edit /etc/php/X.X/cli/php.ini and set memory_limit = 1024M or run the CLI upgrade with an inline override:
php -d memory_limit=2048M tools/upgrade.php upgrade
Verifying Successful Completion
A successful upgrade will complete all migration steps and display:
[code: upgrade]
Successfully upgraded to version 3.X.X.X
Immediately disable display_errors and show_stacktrace in config.inc.php once the upgrade is finalized.
Step-by-Step Action Plan
Do Not Re-Run on Corrupted State
Immediately halt the upgrade process; running the script again on a partially migrated database will trigger duplicate key errors.
Enable Verbose Error Logging
In config.inc.php, set debug = On and show_stacktrace = On to expose the exact failing SQL query and file path.
Analyze Fatal Error Stack Trace
Inspect terminal output or /var/log/apache2/error.log (or PHP-FPM log) to identify the specific table and column causing the exception.
Restore Pre-Upgrade Database Snapshot
Drop the half-migrated database and restore the clean pre-upgrade backup from your snapshot.
Apply Pre-Migration SQL Fix & Retry
Execute the required schema repair query on the clean database and re-run php tools/upgrade.php upgrade.
Questions People Usually Ask
Why does an upgrade fail with "Table already exists" when re-run?
When an upgrade halts halfway through, several tables have already been created or altered. Re-running the script from scratch attempts to create those tables again, triggering fatal duplicate table errors. Always restore your clean pre-upgrade snapshot before re-running.
What does "Duplicate entry for key PRIMARY" mean during an OJS upgrade?
This occurs when data normalization scripts combine tables containing duplicate identifiers or when previous manual database edits created duplicate localized setting values. Cleaning duplicates before upgrading resolves this.
Can AcademiaTech rescue an OJS database that failed an upgrade without a backup?
Yes. Our database specialists can perform forensic analysis on partial schemas, identify which migration scripts executed, and manually reconstruct the remaining schema transformations.
Did Your OJS Upgrade Fail Halfway Through?
AcademiaTech provides emergency database rescue for failed OJS migrations, restoring damaged schemas and completing upgrades with 100% data integrity.