Fixing the Parse Error: Syntax Error, Unexpected in WordPress
PHP refused to compile a file, so nothing in it ran. The message names the file and a line, but the line is where PHP gave up, which is often one line after the actual mistake. Here is how to read it and get the site back without the dashboard.
PHP could not compile one file, so the file never ran — fix the character PHP names, usually on the line before the one in the message. Parse error: syntax error, unexpected token "}" in /wp-content/themes/mytheme/functions.php on line 42 gives you the file, the line and the token PHP did not expect. Unlike most WordPress errors, nothing here is about plugins, the database or the server: one file has text in it that is not valid PHP.
Reading the message
PHP 8 reports the offending token in quotes, and sometimes what it wanted instead:
Parse error: syntax error, unexpected token "}", expecting ";" in .../functions.php on line 42
Parse error: syntax error, unexpected end of file in .../functions.php on line 118
Parse error: syntax error, unexpected identifier "add_action" in .../functions.php on line 27
Parse error: syntax error, unexpected token "<", expecting end of file in .../functions.php on line 205
PHP 7 printed the same thing with single quotes, unexpected '}', so older forum answers still apply. What changes is how to read each one:
| Message ends with | Usual cause | Where to look |
|---|---|---|
unexpected token "}", expecting ";" |
Missing semicolon | End of the previous statement |
unexpected end of file |
Unclosed {, ( or string |
Anywhere above; the last line is just where PHP ran out of file |
unexpected identifier "…" |
Previous line not terminated, or curly quotes | The line before |
unexpected token "<" |
A second <?php pasted mid-file |
The pasted snippet |
A token on a line using fn, ?-> or match |
Syntax newer than the server's PHP | The PHP version the site runs |
The line number is the line where the parser stopped, and the parser stops at the first thing that cannot follow what came before. A statement without its semicolon is still a valid beginning until the next line starts, so the report lands one line late. unexpected end of file is the extreme case: the unclosed brace may be a hundred lines up.
Get the site back first
A parse error in an active theme's functions.php or in an active plugin takes the whole site down, and usually the dashboard with it. You need file access — SFTP, SSH or the hosting file manager — to fix it, and there are two ways to do it.
- Undo the edit. If you just pasted a snippet, remove exactly what you pasted. Keep a copy, because you will want to fix and re-add it.
- Isolate the file. If you do not know what changed, rename the plugin's folder in
wp-content/pluginsto deactivate it, as described in disabling plugins without admin access. For a theme, renaming its folder makes WordPress fall back to a default theme if one is installed.
If the site shows "There has been a critical error on this website" instead of the raw parse error, WordPress's fatal error handler caught it. That handler includes E_PARSE in the errors it handles, so the recovery mode email described in critical error works here too: the link lets you log in with the faulty plugin or theme paused.
The one place recovery mode cannot reach is wp-config.php. wp-load.php requires it before wp-settings.php registers the error handler, so a typo in the config file always shows the raw PHP error or a blank page, and the fix is always by hand.
Find the actual mistake
Run the linter on the file. It compiles without executing, so it is safe on production:
php -l wp-content/themes/mytheme/functions.php
It reports the same line as the error, but it lets you test a fix before uploading it. Use the same PHP version as the site — php -v on the server, or the version shown in Tools › Site Health › Info › Server — because the cause can be syntax that one version accepts and another rejects.
Then work through the usual suspects, in this order:
- The previous line. Missing
;,)or,in an array. - The pasted snippet's opening tag. Snippets on the web usually begin with
<?php. A theme'sfunctions.phpalready starts in PHP mode, so a second<?phpin the middle is the "unexpected token<" error. Remove the tag, keep the code. - Curly quotes. Copying from a blog, a chat or a word processor can turn
'into’. PHP does not treat curly quotes as string delimiters, so the string never opens and the error lands wherever the parser gets confused. Retype the quotes. - Closing tags. A
?>at the end offunctions.phpis legal but invites trailing whitespace, which causes headers already sent rather than a parse error. Leave the closing tag out. - Version-specific syntax. Arrow functions (
fn() =>), the nullsafe operator (?->) and match expressions are parse errors on older PHP. A plugin that works on your laptop and fails on the host is often this. After an update in the other direction, removed features show up as fatal errors rather than parse errors — see site not working after a PHP update.
Why the dashboard editor did not save it
The theme and plugin file editors run a loopback check: they save the file, request the site with a one-time key, look for a fatal error in the response and restore the previous version if they find one. A broken edit made in Appearance › Theme File Editor therefore comes back as an error notice quoting the PHP message, with the previous file restored, not as a dead site. If the check cannot reach the site at all, the editor reverts the edit and asks you to upload it another way.
The protection exists only inside those editors. A file manager, an SFTP client or a deploy script writes the file directly, and the first request after that is the one that fails. Code snippet plugins have their own validation, which is one reason they are safer than editing functions.php by hand. If you edit theme files, do it in a child theme so a theme update does not overwrite the fix.
Common mistakes
- Fixing the reported line when the mistake is above it, and adding a second error.
- Deleting the whole of
functions.phpto get the site back. Remove only what changed. - Editing on the server without a copy of the working file.
- Testing with
php -lon a different PHP version from the one the site uses. - Leaving
WP_DEBUG_DISPLAYon after debugging. Log to a file instead — see debug mode.
Verify
php -lon the edited file printsNo syntax errors detected.- The front end and wp-admin both load.
- If recovery mode paused a plugin or theme, resume it from the Plugins or Themes screen and check the notice is gone.
wp-content/debug.log, if logging is on, shows no new parse errors after the fix.
Frequently asked
- The line is where the parser met something it could not accept, not where the mistake is. A missing semicolon or closing bracket on line 41 is only detected when line 42 starts. Read the line above, then the block the line belongs to.
- Since WordPress 4.9 the theme and plugin editors save the file, request the site in the background and roll the change back if that request hits a fatal error. Edits made over FTP, the hosting file manager or a deploy skip that check entirely.
- It can get you into the dashboard with the broken plugin or theme paused, because the fatal error handler treats E_PARSE like any other fatal error. It cannot help with wp-config.php, which is loaded before the handler is registered.