PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Writer\Exception
Syntax error: $currentToken, lookahead: $lookAhead, current
Error message
Syntax error: $currentToken, lookahead: $lookAhead, current char: $currentCharacter
What it means
The catch-all of the Xls formula parser's fact() step: after failing to match the current token as a parenthesis group, cell reference, number, string, function, boolean, or defined-name-shaped identifier, it throws 'Syntax error: {token}, lookahead: {lookAhead}, current char: {char}' exposing the exact parse position. It means the formula contains syntax the BIFF8 writer's grammar does not accept at all.
Source
Thrown at src/PhpSpreadsheet/Writer/Xls/Parser.php:1514
. Calculation::CALCULATION_REGEXP_DEFINEDNAME
. '$/miu',
$this->currentToken
)
&& $this->spreadsheet->getDefinedName($this->currentToken) !== null
) {
$result = $this->createTree('ptgName', $this->currentToken, '');
$this->advance();
return $result;
}
if (Preg::isMatch('/^true|false$/i', $this->currentToken)) {
$result = $this->createTree($this->currentToken, '', '');
$this->advance();
return $result;
}
throw new WriterException('Syntax error: ' . $this->currentToken . ', lookahead: ' . $this->lookAhead . ', current char: ' . $this->currentCharacter);
}
/**
* It parses a function call. It assumes the following rule:
* Func -> ( Expr [,Expr]* ).
*
* @return mixed[] The parsed ptg'd tree on success
*/
private function func(): array
{
$num_args = 0; // number of arguments received
$function = strtoupper($this->currentToken);
$result = ''; // initialize result
$this->advance();
$this->advance(); // eat the "("
while ($this->currentToken !== ')') {
if ($num_args > 0) {
if ($this->currentToken === ',' || $this->currentToken === ';') {View on GitHub (pinned to 65b080eef4)
Solutions
- Use the diagnostic fields in the message: the token plus lookahead identifies the offending construct; search your cells for it.
- Rewrite unsupported constructs (arrays -> cell ranges, table refs -> plain ranges).
- Normalize localized separators and strip stray characters when accepting user formulas.
- Save as Xlsx - its writer emits the formula string without this parse, so syntax the BIFF8 grammar rejects still round-trips.
Example fix
// before
$sheet->getCell('C3')->setValue('=SUM(Table1[Amount])'); // structured reference
(new \PhpOffice\PhpSpreadsheet\Writer\Xls($spreadsheet))->save('out.xls');
// Syntax error: Table1[Amount], lookahead: ...
// after: plain range equivalent
$sheet->getCell('C3')->setValue('=SUM(Sheet2!A2:A99)');
// or keep the original formula and write Xlsx instead
(new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet))->save('out.xlsx'); Defensive patterns
Strategy: try-catch
Validate before calling
/** Reject formula constructs the BIFF8 grammar cannot parse before saving Xls. */
function formulaIsBiff8Safe(string $v): bool
{
if ($v === '' || $v[0] !== '=') {
return true;
}
// structured references: Table1[Col], array constants: {1,2}, sheet-qualified refs handled elsewhere
if (preg_match('/\w+\[[^]]*\]/', $v) || preg_match('/\{[\d.," ]+\}/', $v)) {
return false;
}
return true;
}
foreach ($sheet->getCoordinates() as $coord) {
$v = $sheet->getCell($coord)->getValue();
if (is_string($v) && !formulaIsBiff8Safe($v)) {
throw new RuntimeException("Formula not supported by Xls writer at {$coord}: {$v}");
}
} Try / catch
try {
(new \PhpOffice\PhpSpreadsheet\Writer\Xls($spreadsheet))->save($path);
} catch (\PhpOffice\PhpSpreadsheet\Writer\Exception $e) {
if (str_starts_with($e->getMessage(), 'Syntax error:')) {
// message contains token + lookahead: find the cell, then fall back to Xlsx or report
$token = substr($e->getMessage(), strlen('Syntax error:'));
// ... locate and log offending cells, or:
(new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet))->save(preg_replace('/\.xls$/', '.xlsx', $path));
} else {
throw $e;
}
} Prevention
- Constrain user-entered formulas to an allow-listed grammar (functions and reference shapes you have tested with the Xls writer).
- Normalize localized separators (';' vs ',') and strip stray whitespace/quotes when importing formulas.
- Add an integration test that saves your full representative template set as Xls on every release.
When it happens
Trigger: Formulas using constructs outside the parser grammar: array constants ({1,2;3,4}), structured/table references (Table1[Amount]), the intersection (space) or union (,) operators, localized argument separators typed as text, or stray characters from string concatenation bugs.
Common situations: Copy-pasting modern Excel formulas into a system that exports legacy Xls; users pasting from localized Excel where list separators were ',' vs ';'; formula fragments joined with a missing operator ('=A1B2'); data imports that leave stray quotes/whitespace inside formulas.
Related errors
- Unknown token $token
- Unknown range separator
- ')' token expected.
- Cannot yet write formulae with defined names to Xls
- Unknown sheet name $ext_ref in formula
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/485bd26997cb8f60.
Report an issue: GitHub.