Hi everyone,
After updating Ghost to version 5.117.0, my subscription flow stopped working correctly. When a user subscribes, Ghost attempts to send the magic link, but returns a 400 error and fails silently. I discovered this is related to an invalid internal filter referencing a newsletter ID that was previously deleted (or at least, not visible in the admin panel anymore).
What I found
The error appears consistently in the production.error.log as follows:
“message”: “Error parsing filter”,
“stack”: “QueryError: Query Error: unexpected character in filter at char 2\n(tags:+id:-67e539196fd4d6b\n------^\nExpecting ‘NOT’, ‘LBRACKET’, ‘NULL’, ‘TRUE’, ‘FALSE’, ‘NUMBER’, ‘NOW’, ‘LITERAL’, ‘STRING’, ‘CONTAINS’, ‘STARTSWITH’, ‘ENDSWITH’, ‘GT’, ‘LT’, ‘GTE’, ‘LTE’, got ‘AND’”,
“level”: “normal”,
“statusCode”: 400
The filter tags:+id:-67e539196fd4d6b is malformed and invalid in NQL.
What I tried
Changing theme (to Casper and others)
Removing all content filters and routes
Disabling portal and newsletters from admin
Searching and deleting references in:
custom_theme_settings
settings
routes.yaml
Exported the JSON and found the offending newsletter ID 67e539196fd4d6b149f85728 in the newsletters block
Tried deleting the newsletter from the DB, but got a foreign key constraint error
Had to manually delete related rows from:
email_recipients
email_batches
emails
Then the newsletters table
Even after that, Ghost kept throwing the error, possibly due to config cache or other leftover internal reference
Impact
The magic link for new subscribers fails
Ghost throws a 400 error with a broken filter
There's no clear way to clean this from the admin UI
This only started happening after upgrading to 5.117.0 — everything worked fine before
Suggestion / Help request
There should be a more graceful way for Ghost to:
Ignore or skip malformed filters that no longer point to active objects
Cleanly delete newsletters (with cascading deletes for associated data)
Warn admins about internal config inconsistencies before or after upgrading
Any advice on how to fully clean this issue would be greatly appreciated — or if this should be escalated as a bug.
Thanks a lot!
—Edmundo