Debug Ghosts, Part VI
How a single Aria checksum error masqueraded as a PHP, PDO, and permissions failure
The Symptom That Wouldn’t Stay Fixed
This was one of those bugs I’d seen before — the kind that never quite goes away.
On Windows (XAMPP), my local TFOL instance would suddenly refuse to connect to the database:
SQLSTATE[HY000] [1045] Access
denied for user 'Geoff'@'localhost'
Classic permissions error.
And yet…
-
The user existed
-
The password was correct
-
Privileges were granted
-
phpMyAdmin mostly worked — until it didn’t
Clicking Privileges in phpMyAdmin reliably triggered a deeper error:
#1030 - Got error 176 "Read
page with wrong checksum" from storage engine Aria
That message turned out to be the key.
The False Trail: Everything Looked Like Permissions
At first glance, everything pointed in the wrong direction:
-
PDO error → must be credentials
-
phpMyAdmin login works → user exists
-
Grant tables look fine → privileges must be correct
-
Recreating users → no effect
-
Matching passwords → no effect
This was the classic Debug Ghost pattern:
Every fix appeared to work — until it didn’t.
The mistake would have been reinstalling XAMPP (again).
Instead, I stopped and asked a better question:
What if the database is lying to me?
The Real Culprit: Aria System Table Corruption
MariaDB (used by XAMPP) stores many system tables using the Aria storage engine — including tables that power:
-
users
-
privileges
-
roles
-
phpMyAdmin’s Privileges UI
When those tables are corrupted, you get phantom failures:
-
users appear to exist
-
grants appear correct
-
authentication randomly fails
-
admin tools partially work
The smoking gun appeared during repair attempts:
info : Wrong CRC on datapage at 21815info : Wrong CRC on datapage at 21816...warning : Number of rows changed from 4 to 1status : OK
That’s Aria saying:
“I found corruption. I fixed what I could. Some rows are gone.”
And those missing rows?
They were privilege-related.
The Fix (The Right Way)
Step 1 — Protect the real data
Before touching system tables, I backed up what mattered:
.\mysqldump -u root -p focus_local > C:\temp\focus_local_backup.sql
SQL dumps of system databases failed — another clue.
Step 2 — Repair the MySQL system database directly
.\mysqlcheck -u root -p --host=127.0.0.1 --port=3306 mysql --auto-repair --extended
This was the turning point.
Every mysql.* table returned:
OK
For the first time in a long time, phpMyAdmin Privileges loaded cleanly.
Step 3 — Recreate users after repair
Because corruption had altered row counts, users and grants were re-stamped:
DROP USER IF EXISTS 'Geoff'@'%';CREATE USER 'Geoff'@'%' IDENTIFIED BY '********';GRANT ALL PRIVILEGES ON focus_local.* TO 'Geoff'@'%';FLUSH PRIVILEGES;
Step 4 — Normalize the connection (Windows matters)
On Windows, ambiguity causes trouble.
The final DSN was made explicit:
mysql:host=127.0.0.1;port=3306;dbname=focus_local;charset=utf8mb4
No localhost.
No guessing.
The Moment of Truth
-
TFOL logged in ✔
-
phpMyAdmin Privileges loaded ✔
-
No more 1045 errors ✔
-
No reinstall ✔
-
No data loss ✔
A bug that had lingered for years was finally gone.
Lessons Learned (Debug Ghosts Rule #6)
-
Permissions errors can be lies
-
If admin tools error, believe them
-
Aria corruption creates phantom bugs
-
Back up data, then repair system tables
-
Never reinstall before repairing
-
On Windows, always specify host + port
Epilogue
This wasn’t a PHP bug.
It wasn’t a PDO bug.
It wasn’t even a permissions bug.
It was a corrupted database pretending to be healthy — and that’s the most dangerous kind of Debug Ghost there is.
Posted in ghost-stories by TFOL BLOG