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

We should not be expecting a condition

Error message

We should not be expecting a condition

What it means

BranchPruner::closingBrace() runs when the parser closes an IF( whose state is still in the condition slot, meaning the IF has only one argument and no true/false branch; it then throws 'We should not be expecting a condition' and parsing aborts. Excel likewise requires at least two arguments for IF.

Source

Thrown at src/PhpSpreadsheet/Calculation/Engine/BranchPruner.php:168

            } elseif ($this->thenMap[$this->pendingStoreKey]) {
                $this->thenMap[$this->pendingStoreKey] = false;
                $this->elseMap[$this->pendingStoreKey] = true;
            } elseif ($this->elseMap[$this->pendingStoreKey]) {
                throw new Exception('Reaching fourth argument of an IF');
            }
        }
    }

    public function closingBrace(mixed $value): void
    {
        if (!empty($this->pendingStoreKey) && $this->braceDepthMap[$this->pendingStoreKey] === -1) {
            // we are closing an IF(
            if ($value !== 'IF(') {
                throw new Exception('Parser bug we should be in an "IF("');
            }

            if ($this->conditionMap[$this->pendingStoreKey]) {
                throw new Exception('We should not be expecting a condition');
            }

            $this->thenMap[$this->pendingStoreKey] = false;
            $this->elseMap[$this->pendingStoreKey] = false;
            --$this->braceDepthMap[$this->pendingStoreKey];
            array_pop($this->storeKeysStack);
            $this->pendingStoreKey = null;
        }
    }

    public function currentCondition(): ?string
    {
        return $this->currentCondition;
    }

    public function currentOnlyIf(): ?string
    {
        return $this->currentOnlyIf;

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Always supply at least condition plus true-branch: =IF(A1>0, 1, 0).
  2. When building conditionals programmatically, default the missing pieces explicitly rather than omitting them.
  3. Lint formula strings for IF( occurrences closed with no top-level comma before the matching ).
  4. Catch PhpOffice\PhpSpreadsheet\Calculation\Exception around calculation of untrusted formulas and report the cell.

Example fix

// before - throws 'We should not be expecting a condition'
$cell->setValue('=IF(A1>0)');

// after
$cell->setValue('=IF(A1>0, 1, 0)');
Defensive patterns

Strategy: try-catch

Validate before calling

// An IF( with no top-level comma before its closing paren is incomplete.
function ifMissingBranches(string $formula): bool
{
    return (bool) preg_match('/=\s*IF\([^,]*\)/i', $formula);
}

Try / catch

use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcException;

try {
    $value = Calculation::getInstance($spreadsheet)->calculateFormula($formula);
} catch (CalcException $e) {
    // 'We should not be expecting a condition' -> IF() had only its condition
    $value = '#ERROR';
}

Prevention

When it happens

Trigger: Formulas like =IF(A1>0) or =IF(A1) (parentheses close right after the condition, no comma); nested cases such as =IF(IF(A1),2,3); truncated formula strings cut off before the branches.

Common situations: Formulas built by concatenation where the branches were never appended; optional-branch code that omits the else part entirely instead of writing a default; users editing a formula and deleting the branches; data-import pipelines that truncate long formula strings.

Related errors


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