PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Calculation\Exception

Token with id $id does not exist.

Error message

Token with id $id does not exist.

What it means

FormulaParser::getToken(int $id) indexes the token list built by parseToTokens(); an out-of-range id throws Calculation\Exception with 'Token with id $id does not exist.' An empty or whitespace-only formula yields zero tokens, so even getToken(0) with the default id can throw. The exception is a plain PHP exception, not an Excel error value.

Source

Thrown at src/PhpSpreadsheet/Calculation/FormulaParser.php:99

     * Get Formula.
     */
    public function getFormula(): string
    {
        return $this->formula;
    }

    /**
     * Get Token.
     *
     * @param int $id Token id
     */
    public function getToken(int $id = 0): FormulaToken
    {
        if (isset($this->tokens[$id])) {
            return $this->tokens[$id];
        }

        throw new Exception("Token with id $id does not exist.");
    }

    /**
     * Get Token count.
     */
    public function getTokenCount(): int
    {
        return count($this->tokens);
    }

    /**
     * Get Tokens.
     *
     * @return FormulaToken[]
     */
    public function getTokens(): array
    {
        return $this->tokens;

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Bound the loop with $i < $parser->getTokenCount()
  2. Iterate getTokens() directly instead of indexing by id
  3. Early-return when getTokenCount() === 0
  4. Recompute indexes whenever the parsed formula changes

Example fix

// before
for ($i = 0; $i <= $parser->getTokenCount(); $i++) { // off-by-one: last id does not exist
    process($parser->getToken($i));
}

// after
$count = $parser->getTokenCount();
for ($i = 0; $i < $count; $i++) {
    process($parser->getToken($i));
}
Defensive patterns

Strategy: validation

Validate before calling

$count = $parser->getTokenCount();
if ($count === 0) {
    return; // nothing to walk
}
for ($i = 0; $i < $count; $i++) {
    $token = $parser->getToken($i);
}

Type guard

function tokenExists(FormulaParser $parser, int $id): bool
{
    return $id >= 0 && $id < $parser->getTokenCount();
}

Try / catch

try {
    $token = $parser->getToken($id);
} catch (\PhpOffice\PhpSpreadsheet\Calculation\Exception $e) {
    // 'Token with id N does not exist.' - fix the index bound, do not retry
}

Prevention

When it happens

Trigger: Off-by-one loop: for ($i = 0; $i <= $parser->getTokenCount(); $i++) - the last iteration is out of range; calling getToken() on a parser constructed with ''; keeping a token index across a re-parse of a different formula.

Common situations: Walking tokens to rewrite formulas (bulk reference rewriting); token-stream analysis tooling; processing migrated sheets where some cells contain empty formula strings.

Related errors


AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17). Data as JSON: /api/errors/27e937770d25a790. Report an issue: GitHub.