{"record":{"id":"719f2a47b8d8fde6","repo":"mongodb/laravel-mongodb","slug":"bson-type-s-cannot-be-converted-to-string","errorCode":null,"errorMessage":"BSON type %s cannot be converted to string","messagePattern":"BSON type (.+?) cannot be converted to string","errorType":"exception","errorClass":"MathException","httpStatus":null,"severity":"error","filePath":"src/Eloquent/DocumentModel.php","lineNumber":330,"sourceCode":"\n        return parent::isJsonCastable($key);\n    }\n\n    /**\n     * @param mixed $value\n     *\n     * @inheritdoc\n     */\n    protected function asDecimal($value, $decimals)\n    {\n        // Convert BSON to string.\n        if ($this->isBSON($value)) {\n            if ($value instanceof Binary) {\n                $value = $value->getData();\n            } elseif ($value instanceof Stringable) {\n                $value = (string) $value;\n            } else {\n                throw new MathException('BSON type ' . $value::class . ' cannot be converted to string');\n            }\n        }\n\n        return parent::asDecimal($value, $decimals);\n    }\n\n    public function fromJson($value, $asObject = false)\n    {\n        if (is_array($value)) {\n            return $asObject ? (object) $value : $value;\n        }\n\n        return parent::fromJson($value, $asObject);\n    }\n\n    /**\n     * Change to mongo native for decimal cast.\n     *","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/mongodb/laravel-mongodb/blob/0634653039468ceb0268a69192bdac64469ed043/src/Eloquent/DocumentModel.php#L312-L348","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n$model->amount = $doc->amount; // raw Decimal128/BSON value\n// after\n$model->amount = (string) $doc->amount; // convert BSON to string first","handlingStrategy":"type-guard","validationCode":"if (is_bson($value) && !$value instanceof \\MongoDB\\BSON\\Binary && !$value instanceof \\Stringable) {\n    $value = (string) json_encode($value);\n}","typeGuard":"function canBeDecimalString(mixed $value): bool {\n    return !is_bson($value) || $value instanceof \\MongoDB\\BSON\\Binary || $value instanceof \\Stringable;\n}","tryCatchPattern":"try {\n    $amount = $model->amount; // decimal cast\n} catch (MathException $e) {\n    if (str_starts_with($e->getMessage(), 'BSON type')) {\n        $amount = (string) $rawDoc['amount']; // convert BSON manually\n    } else {\n        throw $e;\n    }\n}","preventionTips":["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"],"tags":["casts","bson","decimal"],"backgroundTag":"type-mismatch","analyzedSha":"0634653039468ceb0268a69192bdac64469ed043","analyzedAt":"2026-09-15T02:56:37.067Z","contentChangedAt":"2026-09-15T02:56:37.067Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}