Common causes
- A missing closing curly brace } for a function, class, if or loop
- An unterminated string, often an apostrophe inside a single-quoted string
- A heredoc or nowdoc whose closing identifier is missing or misspelled
- Short open tags <? used when short_open_tag is Off, so a block is hidden from PHP
- An if: / foreach: block missing its endif; or endforeach;
- A file truncated during upload or FTP transfer
How to fix it
- Lint the file. Run php -l path/to/file.php. On PHP 8 the message often includes Unclosed '{' on line N, which is the block that never closed.
- Match the braces. Open the file in an editor with bracket matching and code folding. Collapse each function and class; the one that swallows the rest of the file is missing its closing brace.
- Check strings and heredocs. Look for strings where syntax highlighting runs on for many lines. For heredoc, the closing identifier (for example EOT;) must match exactly, and before PHP 7.3 it had to start at column 0.
- Replace short open tags. Change <? to <?php everywhere (keep <?= which is always enabled). With short_open_tag = Off, code after <? is treated as HTML, leaving braces unbalanced.
- Re-upload or restore the file. If you did not edit the file recently, compare its size with the original package or your Git copy. A truncated upload is fixed by uploading the file again in binary mode or restoring it from backup.
Lint every PHP file in a project
# single file
php -l functions.php
# whole project, show only failures
find . -name '*.php' -not -path './vendor/*' -print0 \
| xargs -0 -n1 php -l | grep -v '^No syntax errors' How to stop it happening again
- Run php -l in a Git pre-commit hook or CI step
- Use an editor or IDE that highlights unmatched brackets
- Edit live files through Git or SFTP, not a browser-based editor that can save partial files
- Avoid short open tags in shared code