{"record":{"id":"b17df11e1bedc239","repo":"PHPOffice/PhpSpreadsheet","slug":"num-b17df1","errorCode":"#NUM!","errorMessage":"#NUM!","messagePattern":"#NUM!","errorType":"error_code","errorClass":"PhpOffice\\PhpSpreadsheet\\Calculation\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Calculation/Engineering/ConvertOctal.php","lineNumber":169,"sourceCode":"        try {\n            $value = self::validateValue($value);\n            $value = self::validateOctal($value);\n            $places = self::validatePlaces($places);\n        } catch (Exception $e) {\n            return $e->getMessage();\n        }\n\n        $hexVal = strtoupper(dechex((int) self::toDecimal($value)));\n        $hexVal = (PHP_INT_SIZE === 4 && strlen($value) === 10 && $value[0] >= '4') ? \"FF{$hexVal}\" : $hexVal;\n\n        return self::nbrConversionFormat($hexVal, $places);\n    }\n\n    protected static function validateOctal(string $value): string\n    {\n        $numDigits = (int) preg_match_all('/[01234567]/', $value);\n        if (strlen($value) > $numDigits || $numDigits > 10) {\n            throw new Exception(ExcelError::NAN());\n        }\n\n        return $value;\n    }\n}\n","sourceCodeStart":151,"sourceCodeEnd":175,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Calculation/Engineering/ConvertOctal.php#L151-L175","documentation":"#NUM! from the octal validator used by OCT2BIN, OCT2DEC and OCT2HEX. ConvertOctal::validateOctal() counts digits matching [0-7] and throws Calculation\\Exception('#NUM!') when the string contains other characters (notably 8 and 9, which are not octal digits) or when it has more than 10 digits - Excel octal numbers are capped at 10 characters with the sign in the top bit.","triggerScenarios":"=OCT2DEC(\"789\") (8/9 invalid), =OCT2DEC(\"12345678901\") (11 digits), =OCT2BIN(\"12 3\") (space); PHP calls ConvertOctal::toDecimal('999') or a decimal phone-number-like string passed by mistake.","commonSituations":"Passing decimal digit strings that happen to contain 8 or 9 to an octal conversion; digit strings longer than 10 characters (IDs, phone-like codes); values with whitespace or separators from imports.","solutions":["Validate the string against /^[0-7]{1,10}$/ before calling OCT2* functions.","If the value is really decimal, use ConvertDecimal (DEC2*) functions or decoct() instead of the octal ones.","Check conversion results for '#NUM!' when the strings come from users or files."],"exampleFix":"// before\n$dec = ConvertOctal::toDecimal('789'); // '#NUM!' - 8 and 9 are not octal digits\n\n// after\n$oct = trim('789');\n$dec = preg_match('/^[0-7]{1,10}$/', $oct)\n    ? ConvertOctal::toDecimal($oct)\n    : ConvertDecimal::toHex((int) $oct); // it was decimal after all","handlingStrategy":"validation","validationCode":"$oct = trim((string) $value);\nif (!preg_match('/^[0-7]{1,10}$/', $oct)) {\n    throw new \\InvalidArgumentException('value must be 1-10 octal digits (0-7 only)');\n}\n$dec = ConvertOctal::toDecimal($oct);","typeGuard":"/** OCT2* input: 1-10 characters, digits 0-7 only. */\nfunction isValidOctalString(mixed $v): bool\n{\n    return is_string($v) && preg_match('/^[0-7]{1,10}$/', $v) === 1;\n}","tryCatchPattern":null,"preventionTips":["Watch for decimal-looking strings containing 8 or 9 - they are not octal.","Validate length: more than 10 digits is rejected.","If the source is really decimal, use the DEC2* functions instead."],"tags":["phpspreadsheet","excel-formula","base-conversion","octal","pattern-validation"],"backgroundTag":"excel-num-error","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}