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

Unsupported numeric binary operation

Error message

Unsupported numeric binary operation

What it means

Before doing any encoding detection, XmlScanner::findCharSet() checks whether the payload begins with the bytes \x4c\x6f\xa7\x94, which are '<?xm' in EBCDIC (code page 037/1027 family). An XML file that starts this way is an EBCDIC-encoded document, typically transferred straight from a mainframe; libxml cannot parse it and the scanner blocks it immediately with 'EBCDIC encoding not permitted' at XmlScanner.php:68.

Source

Thrown at src/PhpSpreadsheet/Calculation/Calculation.php:2660

                case '/':
                    if ($operand2 == 0) {
                        //    Trap for Divide by Zero error
                        $stack->push('Error', ExcelError::DIV0());
                        $this->debugLog->writeDebugLog('Evaluation Result is %s', $this->showTypeDetails(ExcelError::DIV0()));

                        return false;
                    }
                    $result = $operand1 / $operand2;

                    break;
                //    Power
                case '^':
                    $result = $operand1 ** $operand2;

                    break;

                default:
                    throw new Exception('Unsupported numeric binary operation');
            }
        }

        //    Log the result details
        $this->debugLog->writeDebugLog('Evaluation Result is %s', $this->showTypeDetails($result));
        //    And push the result onto the stack
        $stack->push('Value', $result);

        return $result;
    }

    /**
     * Trigger an error, but nicely, if need be.
     *
     * @return false
     */
    protected function raiseFormulaError(string $errorMessage, int $code = 0, ?Throwable $exception = null): bool
    {

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Convert the file from EBCDIC to UTF-8 before loading: iconv -f CP037 -t UTF-8 input.xml > input.utf8.xml (pick the CCSID that matches the source system).
  2. Re-transfer the file from the host in ASCII/text mode, or have the generating job emit ASCII/UTF-8 directly.
  3. If your pipeline routinely receives such files, add an upload gate that checks the first 4 bytes and auto-converts (or rejects) before the reader sees them.
  4. Confirm the correct EBCDIC code page (037 vs 1026 vs 500) by round-tripping a known snippet, since national characters differ between pages.

Example fix

// before
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load('mainframe-report.xml');
// throws: EBCDIC encoding not permitted (starts with \x4c\x6f\xa7\x94)

// after - convert EBCDIC (CP037) to UTF-8 before loading
$xml = file_get_contents('mainframe-report.xml');
if (str_starts_with($xml, "\x4c\x6f\xa7\x94")) {
    $xml = mb_convert_encoding($xml, 'UTF-8', 'CP037');
}
$tmp = tempnam(sys_get_temp_dir(), 'xlsx');
file_put_contents($tmp, $xml);
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($tmp);
Defensive patterns

Strategy: validation

Validate before calling

// Detect and (optionally) convert EBCDIC before loading
function normalizeEbcdic(string $path): string
{
    $raw = (string) file_get_contents($path);
    if (str_starts_with($raw, "\x4c\x6f\xa7\x94")) { // EBCDIC '<?xm'
        $raw = mb_convert_encoding($raw, 'UTF-8', 'CP037'); // adjust CCSID if needed
    }
    return $raw;
}

$clean = normalizeEbcdic($path);
$tmp = tempnam(sys_get_temp_dir(), 'xlsx');
file_put_contents($tmp, $clean);
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($tmp);

Try / catch

use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;

try {
    $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($path);
} catch (ReaderException $e) {
    if (str_contains($e->getMessage(), 'EBCDIC')) {
        // re-request the file in ASCII/UTF-8 from the source system, or convert via iconv -f CP037
    }
    throw $e;
}

Prevention

When it happens

Trigger: Calling IOFactory::load() or scanFile() on a file that was encoded in EBCDIC (e.g. CCSID 037/500/1026 on z/OS or AS/400) and copied or FTP'd in binary mode without ASCII conversion. The first four bytes match the EBCDIC '<?xm' magic and the exception fires before BOM or declaration sniffing even runs.

Common situations: Feeds or reports generated on IBM mainframes (z/OS) or IBM i and transferred in binary; SFTP/managed-file-transfer pipelines that skip encoding translation; archives where the file was never converted after leaving the host system.

Related errors


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