`ghost backup` stringified JSON response exceeds the maximum string size for Nodejs and crashes

Issue Summary

  • I have approximately 12,000 posts on my blog. I’m trying to backup my Ghost instance to update it.
  • When I use the cli to do a ghost backup, I get a timeout after 10 seconds.
  • When I make a curl request on the Ghost server bypassing nginx. I get the same 10 second timeout.
  • When I check the logs, I notice that every time I try to make a backup, the ghost server restarts.

What did you expect to happen?

  • I expect to be able to export my blog.

Steps to Reproduce

  1. Start a backup using the CLI, using the admin page, or using CURL on the server itself.

Setup information

Debug Information:
OS: Ubuntu, v22.04.4 LTS
Node Version: v18.20.3
Ghost Version: 5.52.1
Ghost-CLI Version: 1.25.3

How did you install Ghost?
Installed using the guide on the Ghost site on Ubuntu

Provide details of your host & operating system
I’ve tested this by running the same snapshot on servers with 4gb or 8gb of memory.

Database type
MySQL 8
Ver 8.0.37-0ubuntu0.22.04.3 for Linux on x86_64 ((Ubuntu))

Relevant log / error output

[2024-06-13 19:45:57] INFO Ghost is running in production…
[2024-06-13 19:45:57] INFO Your site is now available on ------
[2024-06-13 19:45:57] INFO Ctrl+C to shut down
[2024-06-13 19:45:57] INFO Ghost server started in 0.812s
[2024-06-13 19:45:57] INFO Database is in a ready state.
[2024-06-13 19:45:57] INFO Ghost database ready in 1.091s

You are likely running out of some resource. Try again, but this time prepare in advance by making several more terminal windows open to the server to create a dashboard of what’s happening. In different windows:

  • Logs. journalctl -fu ‘ghost*’
  • htop. Watch memory and CPU
  • df -h. Run it repeatedly to see if you are running out of disk space

After this experiment you should have a clearer idea of the resources and logging
during the failed backup.

To answer a different way:

Fundamentally Ghost is made up assets on the file system and in the database.

So standard tools to backup your Ghost files along with its Nginx files and MySQL apply.

If ghost backup isn’t working for you, you could use generic backup methods.

But is the issue is that you are running out of some resource, that problem may affect all backup methods.

Thank you.

I increased my memory limit for node using:

export NODE_OPTIONS=--max_old_space_size=4096
ghost run

and now can see this error:

[2024-06-19 19:30:08] ERROR "GET /blog/ghost/api/admin/db/" 500 17483ms

An unexpected error occurred, please try again.

"Invalid string length"

Error ID:
    569046a0-2e72-11ef-80d8-ff9031b6d30c

Error Code:
    UNEXPECTED_ERROR

----------------------------------------

RangeError: Invalid string length
    at module.exports.prepareError (/var/www/blog/versions/5.52.1/node_modules/@tryghost/mw-error-handler/lib/mw-error-handler.js:92:19)
    at JSON.stringify (<anonymous>)
    at stringify (/var/www/blog/versions/5.52.1/node_modules/express/lib/response.js:1150:12)
    at ServerResponse.json (/var/www/blog/versions/5.52.1/node_modules/express/lib/response.js:271:14)
    at send (/var/www/blog/versions/5.52.1/node_modules/@tryghost/api-framework/lib/http.js:94:21)
    at /var/www/blog/versions/5.52.1/node_modules/@tryghost/api-framework/lib/http.js:115:13

To try to resolve this, I’ve attempted to update my ghost instance to the latest version. However, when trying to start, I get another issue:

Message: Ghost was able to start, but errored during boot with: Migration lock was never released or currently a migration is running.
Help: If you are sure no migration is running, check your data and if your database is in a broken state, you could run `yarn knex-migrator rollback`.
Suggestion: journalctl -u ghost_test-blog-nominis-es -n 50

checking the logs, I see:

 MigrationsAreLockedError: Migration lock was never released or currently a migration is running.
     at /var/www/blog/versions/5.85.1/node_modules/knex-migrator/lib/locking.js:62:23
     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
     at async DatabaseStateManager.getState (/var/www/blog/versions/5.85.1/core/server/data/db/DatabaseStateManager.js:40:13)
     at async DatabaseStateManager.makeReady (/var/www/blog/versions/5.85.1/core/server/data/db/DatabaseStateManager.js:73:25)
     at async initDatabase (/var/www/blog/versions/5.85.1/core/boot.js:69:5)
     at async bootGhost (/var/www/blog/versions/5.85.1/core/boot.js:537:9)

I tried to change the lock flag in the database, but every time I start Ghost, the lock enables and I get this error.

I’m not immediately sure what would cause that.

Have you tried searching the forum for mentions of the same error?

https://forum.ghost.org/search?context=topic&context_id=48125&q=MigrationsAreLockedError&skip_context=true

I did, but nothing worked so far.

I have a snapshot of the running version (5.52.1) which at least lets me start the server.

Unless you have any other suggestions, I think I’ll have to dump the database and restore it on a new server.

Here in the bug tracker there was a suggestion to run yarn knex-migrator migrate from the Ghost install root dir:

If that doesn’t help, a database dump/restore on to a new server is not a bad idea.

I was unable to get the migrations to work. After digging a bit more, I found that the stringified JSON response exceeds the maximum string size for Nodejs and I’m unable to increase it.

I’m focused on doing a mysql dump and importing that into a new database.

Maybe the Ghost team can figure out a way of doing an export/import with 12,000 posts in the future.

Thanks for the update. This sounds like a bug with Ghost, so I’m moving this to the bugs category.

There should be another way to generate the JSON that doesn’t trigger this. For example, streaming the write of the JSON would only ever hold a limited amount of the JSON in memory.