This is a common issue that crops up for active developers. All of a sudden, their sitemap.xml, sitemap_index.xml, sitemap_posts.xml, etc.. seemingly just stops working - outputting this error:
In short, there's most likely an empty line at the top of the page source. Go ahead and right-click on the sitemap page, then View Page Source. You'll probably see something like this:
Notice how the code begins on line 2 - and not line 1 (as it should). That simple empty line is breaking the XML syntax. So where did it come from?
<?php
and ?>
opening/closing tags (generally plugins or theme files)Let's narrow things down.
The first thing to do is switch your theme to a default one (ie. twentynineteen) - it's possible your theme developer released an update accidentally including a line break or empty space. I've also been guilty of causing this myself numerous times when adding custom lines to my theme's functions.php.
Clear out any caches you might have enabled (Autoptimize, WP-Rocket, Cloudflare, etc). and refresh the page. Once you confirm the default theme is loading, refresh the sitemap page and inspect the source code to see if the empty line is still there. If it is, it's not your theme - let's move on to plugins.
You could deactivate each plugin, one by one - refreshing the page each time to see if empty line disappears. But to speed things along, let's start by confirming the issue is coming from one of the plugins at all.
Rather than disabling all plugins, and enabling one by one - we're going to add a PHP snippet to pseudo-deactivate them all without letting the plugins know. This is a big time saver because there are a bunch of plugins that remove their data from the database automatically on deactivation and need to be reconfigured if they're switched off and on again (ie. Jetpack).
Open your FTP client (ie. Filezilla) or SSH to your site with your terminal and make a file called /wp-content/mu-plugins/plugin-sleep.php. If you don't already have an /mu-plugins/ directory, make one (WordPress autoloads any plugins in this location).
Paste this code into the plugin-sleep.php file you made:
<?php
// Deactivate all plugins without loosing their configurations
add_filter('pre_option_active_plugins', '__return_empty_array');
add_filter('pre_site_option_active_sitewide_plugins', '__return_empty_array');
After this, reload the site. The plugins should all register as deactivated. The odds are you're using a plugin like Yoast to generate your sitemap.xml, but that's deactivated now so the sitemap page will 404. No matter! The empty line should appear at top of any page (including the WordPress 404 page). View the page source again to see if the empty line is still there.
If it's gone, great. You know it's a plugin. Remove /wp-content/mu-plugins/plugin-sleep.php and proceed with toggling the plugins off and one, one by one until you find your culprit.
This step may not apply to you. If you already had an /mu-plugins/ directory and there were other php files in there, try renaming the directory altogether (something like /disable-mu/). This will stop WordPress from automatically loading them. Refresh the page to see If the empty line was coming from one of the files in there.
If the empty line is still there, rename it back to /mu-plugins/.
At this point, it's most likely your wp-config.php or some other WordPress core file.
The next place to stop off is your wp-config.php. Are there any empty lines outside of the <?php
and ?>
tags? Here's what it might look like:
Notice that line 1 is empty and the <?php
opening tag is on line 2? Remove that empty line then refresh the page and view the page source to see if that did the trick.
If you want to search and print a list of all PHP files that begin with an arbitrary empty line, SSH into your site and run this in your terminal:
find . -name "*.php" -type f -size +0 -exec gawk 'STARTFILE{if ($0 == "") print FILENAME}' {} +
If you want to search and print a list of all PHP files that end with an arbitrary empty line, SSH into your site and run this in your terminal:
find . -name "*.php" -type f -size +0 -exec gawk 'FNR==1{if ($0 == "") print FILENAME}' {} +
These commands will help narrow down specific files that contain arbitrary empty lines at the start and end of each file. They won't find any in the middle of the code though. Though if you've gone through all the steps above and are still seeing the issue - it's not the plugin/theme or WordPress core code - so at least you've narrowed it down to some kind of custom script.