Fix PHP Parse error: syntax error, unexpected token When Running PHP Scripts

beginner๐Ÿ˜ PHP2026-05-17| PHP 8.0+, Linux/Windows/macOS, Apache/Nginx, CLI

Error Message

Parse error: syntax error, unexpected token "echo", expecting "," or ";" in /var/www/html/index.php on line 15
#php#syntax-error#parse-error#debug

What's Happening

Before PHP runs a single line, it reads your entire script top-to-bottom and checks the syntax. Hit a missing semicolon, an unclosed bracket, a stray character โ€” it stops right there and throws a Parse error. The script never executes.

The error looks like this:

Parse error: syntax error, unexpected token "echo", expecting "," or ";" in /var/www/html/index.php on line 15

PHP is saying: "I was expecting a comma or semicolon to close out the previous statement, but I found echo instead." The key insight: the real problem is almost never on the reported line. It's usually the line above it โ€” where you left something unclosed.

Debug Process

1. Check the line before the reported line

Go to line 14 โ€” one above the reported line 15. Nine times out of ten, there's a missing semicolon sitting right there.

<?php
// Line 14 โ€” no semicolon at the end
$message = "Hello, world"
echo $message;  // Line 15 โ€” PHP trips here

Add the semicolon and you're done:

$message = "Hello, world";
echo $message;

2. Run PHP syntax check from the terminal

Skip the guessing. Use php -l (lint) to get the exact error without actually running the script:

php -l /var/www/html/index.php

Clean file:

No syntax errors detected in /var/www/html/index.php

Broken file:

Parse error: syntax error, unexpected token "echo", expecting "," or ";" in /var/www/html/index.php on line 15

Make this part of your workflow โ€” run it before every browser test.

3. Enable error display during development

Seeing a blank white page? PHP is hiding the error. Add these three lines at the top of your script temporarily:

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

Prefer to fix it in php.ini instead:

display_errors = On
error_reporting = E_ALL

After editing php.ini, restart your server:

sudo systemctl restart php8.2-fpm
# or
sudo systemctl restart apache2

Common Causes and Fixes

Missing semicolon

Responsible for the majority of these errors. Every PHP statement ends with ; โ€” no exceptions.

// Wrong
$name = "Alice"
echo $name;

// Fixed
$name = "Alice";
echo $name;

Mismatched or unclosed quotes

Open a quote, forget to close it, and PHP will keep reading until it finds a matching quote โ€” consuming everything in between, including newlines.

// Wrong โ€” single quote opened, never closed
$sql = 'SELECT * FROM users WHERE id = 1;
echo $sql;

// Fixed
$sql = 'SELECT * FROM users WHERE id = 1';
echo $sql;

Unclosed parenthesis or bracket

// Wrong โ€” missing closing parenthesis
if ($x > 0 {
    echo "positive";
}

// Fixed
if ($x > 0) {
    echo "positive";
}

Heredoc syntax error

Heredoc has strict formatting rules. On PHP older than 7.3, the closing identifier must sit at column 0 โ€” no leading spaces, no trailing spaces, just the label and a semicolon.

// Wrong on PHP < 7.3 โ€” closing tag is indented
$text = <<<EOT
    Some text
    EOT;

// Fixed for all PHP versions โ€” closing tag at column 0
$text = <<<EOT
    Some text
EOT;

// PHP 7.3+ also accepts consistent indentation on the closing tag
$text = <<<EOT
    Some text
    EOT;

PHP 8 syntax on a PHP 7 server

Named arguments, match expressions, and nullsafe operators (?->) all require PHP 8.0+. Running that code on PHP 7 produces a parse error immediately.

# Check which version is actually running
php --version

# Named arguments โ€” PHP 8.0+ only
array_slice(array: $arr, offset: 0, length: 3);  // Fails on PHP 7.x

Either upgrade to PHP 8 or rewrite the affected code to use positional arguments.

BOM or invisible characters

Files pasted from a Word document or saved with UTF-8 BOM encoding often carry invisible bytes before <?php. PHP sees them, gets confused, and dies before it even reaches your code.

# Check for BOM
file /var/www/html/index.php

# Strip it with sed
sed -i '1s/^\xEF\xBB\xBF//' /var/www/html/index.php

Verify the Fix

Once you've made your change, lint first โ€” then test in the browser. Don't skip the lint step.

php -l /var/www/html/index.php

Then run the script directly or hit it via HTTP:

php /var/www/html/index.php
# or
curl -I http://localhost/index.php

Running Nginx + PHP-FPM? Also check the FPM error log โ€” it often shows errors that don't surface in the browser:

sudo tail -f /var/log/php8.2-fpm.log

Lessons Learned

  • The reported line is rarely the broken line. Look one or two lines above it. The unclosed expression starts there, not where PHP complains.
  • Run php -l constantly. Wire it into your editor's save action or a pre-commit hook. Syntax errors have no business reaching the server.
  • Turn off display_errors in production. Parse errors expose file paths and internal code structure. Log them server-side; never print them to users.
  • Install a real-time linter. PHP Intelephense for VS Code or PhpStorm's built-in inspector catch syntax errors as you type โ€” no waiting until runtime to find out you forgot a semicolon.

Related Error Notes