Hi everyone, and thanks again to the AMTM-OSR team for all the work on these add-ons. I wanted to share some troubleshooting notes about a nasty SQLite issue I hit after updating to ntpMerlin v3.4.14 (March 22 build) and how I worked around it.
Recently my ISP dropped the connection at the same time ntpMerlin was doing a database write, and afterwards my messages log started filling up with errors like:
SQLite3 fatal error: SQLite3 binary is likely corrupted and SQLite header and source version mismatch
At first this looked like real database corruption, but after a lot of digging it turned out to be a classic SQLite "header and source version mismatch" situation: one binary was loading a different
libsqlite3 than it was built for, which SQLite reports as "likely corrupted" even though the database and binary are actually fine.
In my case I had Python 3 from Entware installed, which brought in its own
libsqlite3.so, and the router's native
/usr/sbin/sqlite3 (built with the firmware in 2023) was ending up linked against Entware's newer SQLite library in
/opt/lib (built in 2026). That version mix is exactly what SQLite warns against and is enough to trigger the error.
How ntpMerlin and Entware interacted?
The piece that surprised me is how ntpMerlin ties into this. The script is written to prefer the Entware sqlite3 binary at
/opt/bin/sqlite3 and only fall back to the built-in
/usr/sbin/sqlite3 when the Entware one is missing. On top of that, during startup it checks for
/opt/bin/sqlite3 and, if it's not there, runs
opkg update and
opkg install sqlite3-cli to pull it in from Entware, logging "Installing required version of sqlite3 from Entware."
So ntpMerlin itself doesn't change
LD_LIBRARY_PATH, but it does take Entware and the Entware sqlite3 toolchain as a hard requirement, and Entware in turn adjusts PATH and library paths system-wide on Asuswrt-Merlin systems. That combination meant that once I had Python 3 and Entware's SQLite on the box, other add-ons (like uiDivStats) could also end up tripping over the same mixed-version SQLite libraries even though they weren't specifically using Entware's binaries.
What I had to do to get my router back?
Because of the way ntpMerlin auto-installs
sqlite3-cli when
/opt/bin/sqlite3 is missing, I couldn't just remove the Entware sqlite3 package and be done with it - opening the script menu would immediately try to reinstall it. As a workaround I ended up doing something like a "phantom package":
- I quarantined or removed the Entware sqlite3 binaries and libraries so they wouldn't be picked up unexpectedly.
- I created a symlink so that anything expecting
/opt/bin/sqlite3 would actually hit the native /usr/sbin/sqlite3, which matches the firmware's own libsqlite3.
- I then locked the Entware sqlite3 package using
opkg flag hold sqlite3-cli so that the amtm/ntpMerlin logic wouldn't silently reinstall the real Entware version on the next run.
That was enough to stop the "header and source version mismatch" errors and get both ntpMerlin and other SQLite-using add-ons working again.
Suggestions for more defensive programming behaviour
Routers are already fragile enough ecosystems, and any add-on that pulls in whole subsystems like Entware has a lot of influence over everything else running on the box. Based on this experience, here are two things I'd love to see more of going forward:
- Prefer native tools where possible: Asuswrt-Merlin already ships with a usable
sqlite3 in /usr/sbin/sqlite3. For many use-cases (including what ntpMerlin is doing) it would be safer to default to the native binary and only fall back to /opt when there's a strong reason to do so. I noticed that later release notes mention an export PATH change to give built-in binaries higher priority than Entware ones, which is exactly the sort of change I'm advocating.
- Limit the blast radius of Entware: If an add-on truly must depend on Entware packages, it would help if its scripts wrapped any Entware calls in a carefully controlled environment instead of relying on the global
PATH / LD_LIBRARY_PATH that Entware adds. That way a single package upgrade (like Python 3 and its SQLite) is less likely to affect other built-in tools or unrelated scripts.
I hope this write-up helps anyone else who ends up in the same SQLite mismatch loop, and I'd be very happy to see future ntpMerlin/AMTM-OSR releases continue down the path of preferring native tools and isolating Entware where possible.
Best,
H