There are two versions of this emergency. In the first, you updated your theme and every change you had made to its files is gone: the extra code in functions.php, the CSS tweaks in style.css, the edited header.php. In the second, you tried to do the right thing and created a child theme, and the site broke: “There has been a critical error on this website”, a page with no styling at all, or a message in Appearance, Themes saying The parent theme is missing. Please install the “THEMESLUG” parent theme.
Both come from the same mechanism. A theme update replaces the whole theme folder with a fresh copy, so anything written inside it is lost. A child theme is a separate, small theme that WordPress loads alongside its parent, so your changes survive updates, but it only works if its header, stylesheet loading and PHP code follow a few strict rules. This guide covers recovering lost edits first, then building or repairing the child theme so it does not happen again.
What is happening
When a child theme is active, WordPress treats two folders as one theme:
| Piece |
How the child and parent combine |
style.css header |
The child’s Template: line names the parent folder. This is the only thing that makes it a child theme. |
| Template files (classic themes) |
A file in the child with the same name as one in the parent replaces it, for example header.php or single.php. |
| Templates and parts (block themes) |
Same rule for templates/*.html and parts/*.html. |
functions.php |
Both run. The child’s file loads first, immediately before the parent’s. |
theme.json (block themes) |
Merged. The child only needs the settings it changes. |
| Stylesheets |
Neither is loaded automatically. Each must be enqueued by PHP, either by the parent or by the child. |
The update problem is simpler: WordPress (or a premium theme’s updater) downloads the new version, deletes the old folder and puts the new one in its place. There is no merge. Edits made through Appearance, Theme File Editor while the parent was active were made to the parent folder, so they are lost too.
Before you start
You need SFTP or your panel’s file manager, and ideally SSH with WP-CLI. Take a full backup (files and database) before you change anything, and if you have just lost edits, stop updating or reinstalling the theme, because every reinstall overwrites any chance of recovering files from the server.
How to run commands in this guide:
- Server commands run in an SSH terminal in the site folder (the one with
wp-config.php). Your host may name the tool wp or wp-cli.
- Your computer:
diff and unzip are built into macOS and Linux. On Windows, use WSL, or a visual comparison tool such as WinMerge.
- Theme files live in
wp-content/themes/. You edit them with SFTP, the file manager, or a terminal editor.
Step 1: If the site is down, read the error first
A child theme fatal error shows the “critical error” page, and WordPress usually emails the admin a recovery mode link. FG-02 covers recovery mode and finding the PHP error log in detail. For child themes, the log line tells you which of the following steps applies:
PHP Fatal error: Cannot redeclare PARENT_FUNCTION() (previously declared in /PATH/wp-content/themes/CHILD_THEME/functions.php:LINE) in /PATH/wp-content/themes/PARENT_THEME/functions.php on line LINE
This is an example log line, not a command. Newer PHP versions word it slightly differently (“Cannot redeclare function”), but the parts are the same.
PARENT_FUNCTION is the function both themes define. CHILD_THEME and PARENT_THEME are the theme folders, and LINE is the line number in each.
- Read it as: “the child defined this first, then the parent tried to define it again”. That is Step 4.
Other common lines are “Failed opening required” with a path inside the child folder (Step 5) and “Call to undefined function” naming a function the child expects the parent to provide (often a parent that was renamed or replaced).
To get the site back immediately, switch to the parent theme:
wp theme activate PARENT_THEME
Run this over SSH in the site folder. PARENT_THEME is the parent’s folder name, from wp theme list. Good output is “Success: Switched to ‘THEME NAME’ theme.” If WP-CLI itself fails with the same fatal error, add --skip-themes to the command so it does not load the broken theme. Without SSH, rename the child theme folder over SFTP; WordPress will fall back to another theme. Expect menu locations and Customizer settings to look different while the parent is active (FG-88 explains why).
Step 2: Recover edits lost in a theme update
Look for a copy before you look for a fix
In order of how likely they are to still have your code:
- Your host’s backups. Most hosting panels let you browse or restore a single folder from a daily backup. Restore the old theme folder to a different name (for example
THEMESLUG-old), not over the live theme.
- A backup plugin’s archive, which you can download and unzip on your computer.
- Your own computer or a previous developer’s. Anyone who edited over SFTP may still have the files locally.
- A staging copy that was not updated.
- Old copies on the server, such as
functions.php.bak or an upgrade-temp-backup folder in wp-content. WordPress keeps a temporary backup during updates and removes it afterward, so do not count on it, but check.
Find exactly what was changed with diff
The old folder contains the parent version you were running plus your edits. To separate the two, compare it with a clean copy of that same version. For themes from the WordPress.org directory, clean copies of every release can be downloaded:
curl -O https://downloads.wordpress.org/theme/THEMESLUG.OLD_VERSION.zip
unzip THEMESLUG.OLD_VERSION.zip -d clean
diff -ru clean/THEMESLUG RESTORED_FOLDER > my-changes.diff
Run these on your computer, in an empty folder, after downloading the restored theme folder from your backup.
THEMESLUG is the theme’s folder name. OLD_VERSION is the version you were running before the update, from the Version: line in the restored folder’s style.css.
RESTORED_FOLDER is the path of the restored old theme folder.
-O saves the download under its own file name. -d clean unzips into a folder called clean.
diff -r compares the folders recursively, -u shows each change with context, and > saves the result.
Good output is a short file where lines beginning with + are your additions and lines beginning with - are original lines you changed. Those are the edits to move into a child theme. A huge diff usually means the version numbers do not match; recheck OLD_VERSION. For premium themes, download the matching old version from the vendor’s account area if they offer previous versions, or compare against the new version and read the diff carefully, because it will mix your edits with the vendor’s changes.
Nothing to restore?
Without a backup, the edits are gone from the server. Rebuild them from what you can still see: an archived copy of the site in the Wayback Machine shows the old HTML and CSS output, and an old browser tab may still hold the stylesheet.
Step 3: Create the child theme properly
The folder and style.css header
Create a new folder in wp-content/themes/, for example THEMESLUG-child, and add a style.css file:
/*
Theme Name: CHILD_THEME_NAME
Template: PARENT_FOLDER
Version: 1.0.0
Description: Child theme for PARENT_THEME_NAME
*/
This is the top of the file you create, wp-content/themes/THEMESLUG-child/style.css.
CHILD_THEME_NAME is any name you like; it is what appears in Appearance, Themes.
PARENT_FOLDER must match the parent’s folder name exactly, including case, not its display name. For Twenty Twenty-Five, the display name has spaces and capitals but the folder is twentytwentyfive. Check with wp theme list or by looking in wp-content/themes.
PARENT_THEME_NAME is only a description for you.
Good result: Appearance, Themes shows the child with the parent’s name mentioned underneath. Bad result: it appears under Broken Themes with one of the messages in the table in Step 6.
Load the stylesheets the current way
The old method, an @import line in the child’s style.css, is no longer recommended: it makes the browser download the stylesheets one after the other. The theme handbook’s approach depends on what the parent already loads, so open the parent’s functions.php and search for wp_enqueue_style.
- If the parent loads its own stylesheet with
get_template_directory_uri() or get_parent_theme_file_uri(), the parent CSS is already handled. You only need to load the child’s style.css.
- If the parent loads
get_stylesheet_uri(), that function returns the active theme’s stylesheet, which is now the child’s. The parent’s CSS stops loading, which is the classic “child theme has no styling” bug. You need to load the parent’s file yourself.
- Many block themes load no stylesheet at all, because styling comes from
theme.json. Load the child’s style.css only if you put CSS in it.
A child functions.php that covers the common classic theme case looks like this:
<?php
add_action( 'wp_enqueue_scripts', 'CHILD_PREFIX_enqueue_styles' );
function CHILD_PREFIX_enqueue_styles() {
$parent = wp_get_theme()->parent();
wp_enqueue_style(
'CHILD_PREFIX-parent-style',
get_parent_theme_file_uri( 'style.css' ),
array(),
$parent ? $parent->get( 'Version' ) : null
);
wp_enqueue_style(
'CHILD_PREFIX-style',
get_stylesheet_uri(),
array( 'CHILD_PREFIX-parent-style' ),
wp_get_theme()->get( 'Version' )
);
}
This goes in a new file, wp-content/themes/THEMESLUG-child/functions.php.
CHILD_PREFIX is a short unique prefix for your child theme, such as acme_child. Use it on every function and handle you add so nothing clashes with the parent or plugins.
get_parent_theme_file_uri( 'style.css' ) gives the URL of the parent’s stylesheet. Skip the first wp_enqueue_style call if the parent already loads its own CSS, or the file loads twice.
- The
array( 'CHILD_PREFIX-parent-style' ) dependency makes the child CSS load after the parent’s, so your rules win.
- The version arguments add
?ver= to the URLs. Bumping the child’s Version: header forces browsers to fetch your new CSS.
To check, view the page source and search for style.css. Good output shows the parent stylesheet once, then the child’s. Two copies of the parent, or none, means you need to adjust which calls you keep.
Block theme child themes
For a block theme, style.css with the header is all you need to start. Add a theme.json containing only the settings you change; WordPress merges it over the parent’s. Copy individual templates or parts into templates/ or parts/ with the same file names only when you need to change them. FG-89 explains how Site Editor changes in the database sit above both themes.
Move the recovered edits
Put CSS into the child’s style.css. Put PHP additions into the child’s functions.php, renamed with your prefix. Copy edited template files into the same relative path in the child, then reapply your edits to a fresh copy of the current parent file, not the old one (Step 7 explains why).
Step 4: Fix “Cannot redeclare” fatal errors
The theme handbook warns against copying the parent’s functions.php into the child, and this is why. The child file runs first and defines, say, PARENT_FUNCTION(). Then the parent’s file runs and defines it again, which PHP does not allow.
How to fix it, depending on what you wanted:
- You copied the whole file: delete everything from the child’s
functions.php except your own additions.
- You wanted to replace one parent function: check whether the parent wraps it in
if ( ! function_exists( 'PARENT_FUNCTION' ) ). Themes that do this are “pluggable”, and a child version with the same name replaces the parent’s cleanly because the child loads first. If there is no such wrapper, you cannot replace it by name.
- The function is not pluggable: find where the parent uses it, usually through
add_action or add_filter. Remove the parent’s hook and add your own function under a new name:
add_action( 'after_setup_theme', function () {
remove_action( 'HOOK_NAME', 'PARENT_FUNCTION', PRIORITY );
add_action( 'HOOK_NAME', 'CHILD_PREFIX_replacement', PRIORITY );
} );
This goes in the child’s functions.php.
HOOK_NAME and PRIORITY must match the parent’s own add_action line exactly; find it by searching the parent theme for the function name. If the parent gives no priority, it is 10.
- Wrapping it in
after_setup_theme makes sure the parent’s hook exists before you remove it, since the child loads first.
CHILD_PREFIX_replacement is your new function, defined elsewhere in the same file.
Good result: no fatal error, and your function’s output appears in place of the parent’s. If the parent’s output still shows, the hook name or priority does not match, and remove_action silently did nothing.
Step 5: Fix wrong paths in the child theme
Functions with “template” in the name point to the parent; functions with “stylesheet” point to the child. Mixing them up produces “Failed opening required” fatals or missing images and scripts.
| Function |
Returns |
get_template_directory(), get_parent_theme_file_path() |
Parent folder path |
get_stylesheet_directory() |
Child folder path |
get_theme_file_path(), get_theme_file_uri() |
Child file if it exists, otherwise the parent’s |
Code copied from the parent that uses get_template_directory() . '/inc/FILE.php' keeps loading the parent’s file, which is usually what you want. Code that uses get_stylesheet_directory() will look in the child and fail unless you copied that file too. Use get_theme_file_path( 'inc/FILE.php' ) when you want “child first, parent as fallback”.
Step 6: Fix broken theme messages
Appearance, Themes lists invalid themes under Broken Themes with a reason:
| Message |
Cause and fix |
| The parent theme is missing. Please install the “THEMESLUG” parent theme. |
The Template: value does not match any folder. Install the parent, or correct the spelling and case of the value. |
| Stylesheet is missing. |
No style.css in the folder, often because a zip was extracted one level too deep (THEMESLUG-child/THEMESLUG-child/style.css). |
| The theme defines itself as its parent theme. |
Template: names the child’s own folder. |
| The “THEMESLUG” theme is not a valid parent theme. |
The named parent is itself broken, or is another child theme. WordPress does not support grandchild themes. |
If a parent theme was deleted while its child was active, the front end breaks. When an administrator next opens Appearance, Themes, WordPress detects that the active theme is invalid and switches the site to the default theme, if one is installed. Reinstall the exact parent and reactivate the child; then reassign menus and settings as described in FG-88.
Step 7: Template overrides that went out of date
A copied template file in the child is frozen at the parent version you copied it from. When the parent updates that file (to fix a bug, add accessibility markup, or support a new feature), your copy keeps the old code. Symptoms include features that work on the parent but not the child, layout glitches after a parent update, and PHP warnings from functions the old template calls in ways the parent no longer supports.
diff -u wp-content/themes/PARENT_THEME/TEMPLATE_FILE wp-content/themes/CHILD_THEME/TEMPLATE_FILE
Run this over SSH in the site folder, once for each file the child overrides.
PARENT_THEME and CHILD_THEME are the two folder names. TEMPLATE_FILE is the relative path, such as header.php or template-parts/content.php.
- Lines with
- exist only in the parent (new upstream code you lack); lines with + exist only in the child (your edits).
Re-copy the current parent file into the child and reapply only your + lines. To list every file the child overrides, compare file lists: cd wp-content/themes/CHILD_THEME && find . -name "*.php" -o -name "*.html".
Plugins that support theme overrides, WooCommerce in particular, have the same problem. WooCommerce lists outdated copies under WooCommerce, Status, in the Templates section, comparing the @version line in each file.
Advanced: Child theme or site plugin?
A child theme is the right home for code that only makes sense with that theme: template overrides, styling, theme hook adjustments. Code that should survive a redesign (custom post types, shortcodes, tracking snippets, redirects, user role changes) belongs in a small site-specific plugin or a must-use plugin in wp-content/mu-plugins/. Otherwise, the next theme change takes your business logic with it.
For designers maintaining many sites, a few habits prevent nearly every problem in this guide:
- Keep the child theme in version control and deploy it, rather than editing on the server. Set
define( 'DISALLOW_FILE_EDIT', true ); in wp-config.php on production so nobody edits the parent through the Theme File Editor.
- Record the parent version in the child’s
style.css description or a README, so diffs are easy after updates.
- Prefix everything, and prefer hooks and filters over copying templates. A filter keeps working when the parent template changes; a copied template does not.
- Test parent updates on staging and run the diff from Step 7 for every overridden file.
When to contact your host
Open a ticket when you need a theme folder restored from a backup, or if you cannot reach the error log. Include:
- The theme folder names (parent and child) and the parent version before and after the update.
- The UTC time of the update or of the first error.
- The exact fatal error line from the log, if you have it.
- Which backup date you want restored and where (ask for it in a separate folder, not over the live theme).
For a site that is down right now, start at the Emergency Room.