mongodb/laravel-mongodb · error · MathException
BSON type cannot be converted to string
Error message
BSON type %s cannot be converted to string
What it means
When casting values to a decimal, fromDecimal -> asDecimal must convert the value to a string first. If the value is a BSON type that is neither Binary nor Stringable (e.g. ObjectId, Decimal128 in older drivers, BSONDoc/PackedArray), the library throws MathException because it cannot represent it numerically.
Solutions
- Cast the BSON value to a PHP scalar before assigning, e.g. (string) $value or $value->jsonSerialize()
- Extract payload from Binary values with ->getData() before assignment
- Use the appropriate cast (e.g. keep Decimal128 handling via the library's BSON casts) instead of 'decimal'
- Normalize data at the ETL/import layer so numeric attributes contain strings or numbers
Example fix
// before $model->amount = $doc->amount; // raw Decimal128/BSON value // after $model->amount = (string) $doc->amount; // convert BSON to string first
Defensive patterns
Strategy: type-guard
Validate before calling
if (is_bson($value) && !$value instanceof \MongoDB\BSON\Binary && !$value instanceof \Stringable) {
$value = (string) json_encode($value);
} Type guard
function canBeDecimalString(mixed $value): bool {
return !is_bson($value) || $value instanceof \MongoDB\BSON\Binary || $value instanceof \Stringable;
} Try / catch
try {
$amount = $model->amount; // decimal cast
} catch (MathException $e) {
if (str_starts_with($e->getMessage(), 'BSON type')) {
$amount = (string) $rawDoc['amount']; // convert BSON manually
} else {
throw $e;
}
} Prevention
- Convert BSON types to scalars at the data-import boundary
- Keep ext-mongodb and mongodb driver versions current so Decimal128 stays Stringable
- Avoid assigning raw BSON values to decimal-cast attributes in seeds and factories
When it happens
Trigger: Assigning a raw BSON value (e.g. a MongoDB\BSON\ObjectId or UTCDateTime) to a model attribute declared with the 'decimal' cast, then reading/saving it.
Common situations: Fetching data written by other drivers where numeric fields are stored as Decimal128 but the installed ext-mongodb/driver version returns non-Stringable types; passing raw BSON documents into decimal-cast attributes in seeds or imports.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
AI-assisted analysis of mongodb/laravel-mongodb@0634653039 (2026-09-15).
Data as JSON: /api/errors/719f2a47b8d8fde6.
Report an issue: GitHub.
Appendix: source
Thrown at src/Eloquent/DocumentModel.php:330
return parent::isJsonCastable($key);
}
/**
* @param mixed $value
*
* @inheritdoc
*/
protected function asDecimal($value, $decimals)
{
// Convert BSON to string.
if ($this->isBSON($value)) {
if ($value instanceof Binary) {
$value = $value->getData();
} elseif ($value instanceof Stringable) {
$value = (string) $value;
} else {
throw new MathException('BSON type ' . $value::class . ' cannot be converted to string');
}
}
return parent::asDecimal($value, $decimals);
}
public function fromJson($value, $asObject = false)
{
if (is_array($value)) {
return $asObject ? (object) $value : $value;
}
return parent::fromJson($value, $asObject);
}
/**
* Change to mongo native for decimal cast.
*View on GitHub (pinned to 0634653039)