Resolving WordPress “The response is not a valid JSON response” error

Recently I ran into the following dreaded error when trying to save a Block Editor’ed post:

the response is not a valid JSON response

I had just started testing the Gutenberg block editor on the site, and one of the often-mentioned troubleshooting steps was to disable plugins (All WordPress troubleshooting seems to eventually boil down to disabling some plugin…) or disabling the block editor entirely and using the classic editor.

Disabling the block editor did resolve the problem, and in fact was what I’d done since WP 5 came out since the error existed way back then, but I was determined to finally implement the block editor on this site.

I highly suspected the GT3 PageBuilder that was part of the theme might be the issue, so I disabled the GT3 PageBuilder plugin, and lo and behold, the block editor was able to save the post the next time. Problem solved, but then I lose the PageBuilder content on my site, which I wanted to migrate slowly over to blocks.

Around the same time, I was working with the WordPress REST API for a side project, running queries like

http://site:8888/wp-json/wp/v2/posts

Which would return a response containing properly-formatted JSON array of all posts on the site:

[{"id":3048,"date":"2020-07-07T09:50:54","date_gmt":"2020-07-07T17:50:54","guid":{"rendered":"http:\/\/site:8888\/?p=3048"},"modified":"2020-07-07T11:43:32","modified_gmt":"2020-07-07T19:43:32","slug":"block-editor-draft","status":"publish","type":"post","link":"http:\/\/site:8888\/block-editor-draft\/","title":{"rendered":"Block Editor Draft"},"content":{"rendered":"\n<p>Another block editor post 3456<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container\">\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container\">\n<p>Test<\/p>\n\n\n\n<p>Test<\/p>\n\n\n\n<p>Test<\/p>\n\n\n\n<div class=\"wp-block-media-text alignwide is-stacked-on-mobile is-vertically-aligned-top\"><figure class=\"wp-block-media-text__media\"><img src=\"http:\/\/siw ....rest of JSON content....

Some Luck

Through some luck, I had the GT3 PageBuilder reactivated when I ran the REST API query again, and this time, the REST response contained additional, mysterious script content (highlighted in red) in the beginning, followed by the regular JSON:

        <script type="text/javascript">
            var custom_css = "";

            jQuery("#custom_css_cont").prepend(custom_css);
        </script>
    
        <script type="text/javascript">
            var custom_css = "";

            jQuery("#custom_css_cont").prepend(custom_css);
        </script>
    
        <script type="text/javascript">
            var custom_css = "";

            jQuery("#custom_css_cont").prepend(custom_css);
        </script>
    
        <script type="text/javascript">
            var custom_css = "";

            jQuery("#custom_css_cont").prepend(custom_css);
        </script>
    [{"id":3048,"date":"2020-07-07T09:50:54","date_gmt":"2020-07-07T17:50:54","guid":{"rendered":"http:\/\/site:8888\/?p=3048"},"modified":"2020-07-07T11:43:32","modified_gmt":"2020-07-07T19:43:32","slug":"block-editor-draft","status":"publish","type":"post","link":"http:\/\/site:8888\/block-editor-draft\/","title":{"rendered":"Block Editor Draft"},"content":{"rendered":"\n<p>Another block editor post 3456<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container\">\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-
....rest of JSON content....

It struck me at that point that the <script> tags were being emitted by the GT3 PageBuilder plugin, and was the cause of the JSON being corrupted.

Problem Found!

I ran a quick search for the “custom_css_cont” text within my project files and found the issue: there was a content filter added to create the page builder content, but the filter was eventually responsible for echoing the script content into the REST API output ahead of the JSON:

function gt3_custom_paddings_in_all_modules($custom_css)
{
echo '
<script type="text/javascript">
var custom_css = "' . $custom_css . '";

jQuery("#custom_css_cont").prepend(custom_css);
</script>
';
}

To fix this, I simply commented out the echo statement. Whether this has any material impact to my content isn’t clear yet, but I don’t use any custom CSS in the PageBuilder blocks and I haven’t noticed any other problems, so I’m good with that.

Interestingly enough, the saving of the changed content seems to occur fine in my case even when the JSON error occurs, so I suspect the error may be occurring when the editor reloads the post content via JSON after saving the post.

More evidence to support this is that when loading the initial page for editing (when clicking in the post in the Dashboard), the JSON content is part of the page content; that is, it is not being loaded dynamically by the block editor at that time.

As a separate sanity check, I inspected the editor’s network traffic in my browser’s Developer Tools, and the problematic content was indeed present in the JSON response to the editor save.

So now I have the best of both worlds – the block editor is running fine and the problem in the GT3 Page Builder is bypassed. Since I plan to retire the Page Builder in favour of pure WP Blocks, this is a solution that I can live with and I can transition PageBuilder content over at my own pace.

Conclusion

A potentially handy way to troubleshoot the “the response is not a valid JSON response” error might be to run a query on the WordPress REST API to see if something is affecting the JSON generated by the API.

This information can then be used to find the offending plugin by providing some hints as to where the problem lies, whether just at the plugin level, or at the specific lines of code that can then be modified.

In my case, code from the PageBuilder was deliberately being output into the response, but it would be equally likely that debug messages inadvertently written into code, or compatibility issues caused by updates to PHP may also trigger this behaviour.

There are other solutions for this error that can be found via searching; these include changing the permalink structure and addressing mixed (SSL/ non-SSL) content.