PHPOffice/PhpSpreadsheet · error · SpreadsheetException
Invalid numeric value for datatype Numeric
Error message
Invalid numeric value for datatype Numeric
What it means
setValueExplicit($value, DataType::TYPE_NUMERIC) (type 'n') only accepts null, booleans, and numeric values; the guard rejects anything else before the 0 + $value coercion runs. Strings like 'abc', '', or locale-formatted numbers such as '1.234,56' are not is_numeric() and therefore throw. The check is strict by design so an explicitly numeric cell never holds non-numeric data.
Source
Thrown at src/PhpSpreadsheet/Cell/Cell.php:330
$quotePrefix = true;
}
// no break
case DataType::TYPE_INLINE:
// Rich text
$value2 = StringHelper::convertToString($value, true);
// Cells?->Worksheet?->Spreadsheet
$binder = $this->parent?->getParent()?->getParent()?->getValueBinder();
$preserveCr = false;
if ($binder !== null && method_exists($binder, 'getPreserveCr')) {
/** @var bool */
$preserveCr = $binder->getPreserveCr();
}
$this->value = DataType::checkString(($value instanceof RichText) ? $value : $value2, $preserveCr);
break;
case DataType::TYPE_NUMERIC:
if ($value !== null && !is_bool($value) && !is_numeric($value)) {
throw new SpreadsheetException('Invalid numeric value for datatype Numeric');
}
$this->value = 0 + $value;
break;
case DataType::TYPE_FORMULA:
$this->value = StringHelper::convertToString($value, true);
break;
case DataType::TYPE_BOOL:
$this->value = (bool) $value;
break;
case DataType::TYPE_ISO_DATE:
$this->value = SharedDate::convertIsoDate($value);
$dataType = DataType::TYPE_NUMERIC;
break;
case DataType::TYPE_DRAWING_IN_CELL:View on GitHub (pinned to 65b080eef4)
Solutions
- Validate first: if (is_numeric($value)) then cast with (float) $value (or (int)), else write as TYPE_STRING or handle the bad input
- Use setValue() when the type is not guaranteed - the default binder picks the right datatype
- Normalize locale separators and trim whitespace before the call
Example fix
// before $cell->setValueExplicit($rawInput, DataType::TYPE_NUMERIC); // 'abc' or '1.234,56' throws // after $value = str_replace(['.', ','], ['', '.'], trim($rawInput)); $cell->setValueExplicit(is_numeric($value) ? (float) $value : 0.0, DataType::TYPE_NUMERIC);
Defensive patterns
Strategy: validation
Validate before calling
$value = trim($raw);
if (!is_numeric($value) && $value !== null && !is_bool($value)) {
$cell->setValueExplicit($value, DataType::TYPE_STRING); // keep as text
} else {
$cell->setValueExplicit($value === null ? 0.0 : (float) $value, DataType::TYPE_NUMERIC);
} Type guard
null
Try / catch
null
Prevention
- Run is_numeric() on raw input before forcing TYPE_NUMERIC
- Prefer setValue() for untrusted data - the default binder chooses the datatype
- Normalize locale decimal separators (comma/dot) during CSV import
When it happens
Trigger: setValueExplicit($rawInput, DataType::TYPE_NUMERIC) with unvalidated user/CSV input; locale-formatted decimal strings; empty strings from optional fields; objects without a numeric value.
Common situations: High-throughput writers switched from setValue() (auto-detecting) to setValueExplicit() for performance, then fed raw strings; importing spreadsheets/CSVs where the source column mixes numbers and text.
Related errors
- Item is not a drawing
- Invalid datatype: $dataType
- Conditional is not a Cell Value CF Rule conditional
- #VALUE!
- #REF!
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/09bcfe57d58ecebc.
Report an issue: GitHub.