Fix “Unexpected character in json data” in WP Migrate Lite

Seeing “Migration failed. Unexpected character in json data” or a browser message like “JSON.parse: unexpected character at line 1 column 1 of the JSON data” in WP Migrate Lite usually means this:

The plugin expected a clean JSON response from WordPress.
Instead it received HTML, PHP warnings, or some other text.

Most of the time the real problem is a PHP notice or error from another plugin, or corrupted serialized data that WP Migrate cannot safely read. Below is a step by step path to see the real error, narrow it down to a table or plugin, and then complete your migration cleanly.

WP Migrate Lite shows “Migration failed. Unexpected character in json data” and sometimes “JSON.parse: unexpected character at line 1 column 1 of the JSON data”. How do I fix this?

The short version: WP Migrate Lite is not actually broken.

It is getting back something that is not valid JSON. Your browser then complains.

We need to see what that “something” is, and then fix the source.

To make this easier, here is a quick map:

What this error really means

WP Migrate Lite runs migrations over AJAX.

JavaScript calls admin-ajax.php.
The server should respond with a small JSON blob.
Your browser tries to parse it.

When you see:

  • “Migration failed. Unexpected character in json data” in the UI, or
  • “JSON.parse: unexpected character at line 1 column 1 of the JSON data” in the console

it means the first character of that response was not valid JSON.
Often it is:

  • < from an HTML error page.
  • P from a PHP warning.
  • Text from a plugin that echoed something during the AJAX call.

So our job is to see the raw response, then fix the thing that is being printed there.


Step 1: Look at the actual AJAX response

First confirm what the browser is getting back.

Use your browser dev tools

  1. Open the site where you run WP Migrate Lite.
  2. Open your browser’s developer tools and go to the Network tab.
  3. Filter by XHR or Fetch.
  4. Start the migration again and let it run until it fails.
  5. Find the failing request. It will usually be a call to admin-ajax.php with an action related to wpmdb or wp_migrate.
  6. Click it and look at the Response panel.

You will usually see one of these:

  • Plain HTML like a 403, 404, or 500 HTML error page.
  • PHP warnings or notices mentioning some plugin, theme, or missing table.
  • Debug text someone added with var_dump or print_r.

Whatever is in that response is what we need to fix.

If the response is totally blank or looks like valid JSON, but the UI still complains, move on to log based debugging.


Step 2: Turn on WordPress and WP Migrate debug logging

We want a record of any PHP errors that fire during the migration.

Enable WP debug logging

Edit your wp-config.php file on the site where the migration is running.

Add or update these lines above the line that says /* That's all, stop editing */.

Use a code editor or the file manager from your host.

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

Save the file.

This sends PHP warnings and notices into a file at:

wp-content/debug.log

Trigger the error again

  1. Start the same migration again.
  2. Wait until the “Unexpected character in json data” error appears.
  3. Download or open wp-content/debug.log.
  4. Scroll to the bottom and look at the newest lines.

You are looking for anything that lines up with the time of the failure.

Common patterns:

  • WPMDB Error: Data cannot be unserialized.
  • WordPress database error mentioning a missing or broken table.
  • Warnings or fatals from some other plugin or theme.

If you see WPMDB Error: Data cannot be unserialized, go to the next section.

If you only see errors from another plugin, skip to Fix third party plugin or database errors.


Step 3: Fix “Data cannot be unserialized” issues

When you see log lines like:

WPMDB Error: Data cannot be unserialized. Scope: DeliciousBrains\WPMDB\Common\Replace::recursive_unserialize_replace()

it means WP Migrate tried to read a WordPress field that is supposed to contain a serialized array, but the data is corrupted.

This can happen if:

  • Someone manually edited a serialized value in the database.
  • A plugin stored bad serialized data.
  • Character set or collation changes broke string lengths inside the serialized value.

Often the debug log will also show which table and option or meta key is affected, for example:

WPMDB Find & Replace skipped: {"table":"wp_options","option_name":"some_plugin_option"}

Option A: Exclude the bad table or row from the migration

If the problematic data belongs to a non critical plugin, the fastest fix is to skip it.

In WP Migrate Lite:

  1. Create a new migration or edit the existing profile.
  2. In the Tables section, uncheck plugin specific tables that match what you saw in the log. For example a table for a security plugin or cache plugin.
  3. Run the migration again.

If the error disappears, you know it was that table.

You can usually reinstall or reconfigure that plugin on the target site after the migration.

Option B: Repair or reset the corrupted option or meta

If the log tells you a specific option or meta key is broken and you need that data:

  1. Take a full database backup first.
  2. Use phpMyAdmin or your host’s database tool to open the table it mentions. For example wp_options.
  3. Search for the option or meta key from the log.
  4. Decide whether you can safely reset it.
    • For plugin settings you can usually set it to an empty string, then reconfigure the plugin later.
    • For complex data you may prefer to contact that plugin’s support for a safe value.
  5. Update the row, save, then run the migration again.

If the migration now runs, the corrupted serialized value was the trigger for the JSON error.


Step 4: Fix PHP and database errors from other plugins

In many real world cases the JSON error is only a side effect.

The true problem is a plugin or custom code that throws errors during any request, including AJAX.

In the WordPress forums you will often see logs with lines like:

  • WordPress database error about a missing security plugin table.
  • Deprecated notices that a plugin did not hide.
  • Other warnings being printed in every request.

Those lines can get mixed into the AJAX response that WP Migrate expects to be clean JSON.

Temporarily deactivate noisy plugins and retry

A quick test:

  1. On the source site, temporarily deactivate non essential plugins.
    • Security plugins.
    • Analytics plugins.
    • Debug or maintenance mode plugins.
  2. Run the migration again.

If the migration runs cleanly with plugins disabled, then:

  • Re enable them one by one.
  • After each one, re run a small test migration.

The plugin that brings the error back is the one writing to the AJAX response or triggering a fatal.

Repair missing tables or database issues

If the log shows repeated “WordPress database error” entries from a specific plugin, you have two choices:

  • Repair that plugin’s database tables using its own installer or repair tool.
  • Exclude those tables from the migration if you do not need them on the target.

For example, if a security plugin is logging errors about a missing lockouts table on every request, that noise can show up in the WP Migrate AJAX response.

Fixing or excluding that table typically removes the JSON error on migration.


Step 5: Check for firewalls and server limits that change the response

Sometimes the response is not PHP errors at all.

Instead the server or a firewall is blocking or truncating the AJAX request.

Signs this is the case:

  • The failing AJAX call has an HTTP status such as 403, 404, 413, or 500.
  • The response body is an HTML page from your host or firewall rather than WordPress.

If that matches what you saw in the Network tab:

Things to adjust

Ask your host, or change if you can:

  • Increase max_execution_time and memory_limit to give the migration more room.
  • Raise post_max_size and upload_max_filesize if large payloads are being blocked.
  • Relax mod_security or WAF rules for your WordPress admin URL and specifically for admin-ajax.php.
  • Disable any HTML injection or content modification on admin requests, such as ad or toolbar injectors.

After your host adjusts these, run the migration again and watch the AJAX response. It should now be valid JSON.


Step 6: Narrow the migration to find the bad table

If you still cannot see a clear cause, you can binary search the database.

The idea is simple. Migrate smaller sets of tables until you find the one that triggers the JSON error.

Strategy

  1. In WP Migrate Lite, create a new migration.
  2. First migrate only the core WordPress tables such as:
    • wp_options
    • wp_posts
    • wp_postmeta
    • wp_users
    • wp_usermeta
  3. If that works, add half of the remaining tables and try again.
  4. Repeat until adding a particular group of tables makes the error return.
  5. Then narrow further within that group until you find the single table that causes the failure.

Once you know the exact table, you can:

  • Inspect it for corrupted serialized values.
  • Temporarily truncate or reset non essential entries.
  • Exclude that table completely if it belongs to a plugin you can reset on the target site.

Step 7: Clean up and verify the migration

After you make changes and rerun the migration, check that all is well.

You should see:

  • The migration completes without a JSON or “Unexpected character in json data” popup.
  • In your browser Network tab, the AJAX responses are valid JSON, not HTML or warnings.
  • wp-content/debug.log no longer fills with new errors during a migration run.

If everything looks good, you can leave WP_DEBUG on or set it back to false in wp-config.php once you are finished troubleshooting.


Still stuck

For AI help

If you are still seeing the JSON error and cannot spot the cause, I can walk through your logs and setup with you.

Hit Continue Chat below and send:

  1. A copy of the text you see in the failing AJAX response from the Network tab.
  2. The last twenty or so lines from wp-content/debug.log around the time of the failure.
  3. Whether the migration is database only or includes media and files.
  4. A list of any security or caching plugins running on the source and target sites.

Together we can pinpoint which plugin, table, or server layer is breaking the JSON.

For expert human help

Scroll down to the contact form below. Enter your name, email, and WordPress needs. Atiba will get back to you as soon as possible.

Need human WordPress help?

WP Assistant is a free tool created by Atiba Software, a WordPress design and development company located in Nashville, TN. If you need more personalized WordPress assistance let us know, and we’ll get back to you ASAP!