{"record":{"id":"be601a6b6d26cc9a","repo":"PHPOffice/PhpSpreadsheet","slug":"unable-to-convert-to-string","errorCode":null,"errorMessage":"Unable to convert to string","messagePattern":"Unable to convert to string","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Shared/StringHelper.php","lineNumber":765,"sourceCode":"            if (!Preg::isMatch('/[^-+0-9.]/', $string)) {\n                $minus = $value < 0 ? '-' : '';\n                $positive = abs($value);\n                $floor = floor($positive);\n                $oldFrac = (string) ($positive - $floor);\n                $frac = Preg::replace('/^0[.](\\d+)$/', '$1', $oldFrac);\n                if ($frac !== $oldFrac) {\n                    return \"$minus$floor.$frac\";\n                }\n            }\n\n            return $string;\n        }\n        if ($value === null || is_scalar($value) || $value instanceof Stringable) {\n            return (string) $value;\n        }\n\n        if ($throw) {\n            throw new SpreadsheetException('Unable to convert to string');\n        }\n\n        return $default;\n    }\n\n    /**\n     * Assist with POST items when samples are run in browser.\n     * Never run as part of unit tests, which are command line.\n     *\n     * @codeCoverageIgnore\n     */\n    public static function convertPostToString(string $index, string $default = ''): string\n    {\n        if (isset($_POST[$index])) {\n            return htmlentities(self::convertToString($_POST[$index], false, $default));\n        }\n\n        return $default;","sourceCodeStart":747,"sourceCodeEnd":783,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Shared/StringHelper.php#L747-L783","documentation":"Thrown by StringHelper::convertToString() when the value cannot be losslessly stringified: it is neither null, a scalar (int/float/bool/string), nor an object implementing Stringable — and the method was called with $throw = true (the default). With $throw = false it would instead return the $default string. Most writers and cell-string paths funnel through this helper, so the exception surfaces at save time.","triggerScenarios":"Setting a cell value (or writer option) to a PHP array, a plain stdClass, a SimpleXMLElement/DOMNode, an enum without __toString, or a Closure — then calling a writer's save() or any API that calls StringHelper::convertToString($value) with default flags. Example: $sheet->setCellValue('A1', ['a' => 1]) followed by Csv/Xls export.","commonSituations":"Writing DB rows (arrays from PDOfetchAll) directly into cells; passing ORM entity objects without __toString; passing enums/DOM nodes from XML processing; inconsistent types arriving from JSON payloads.","solutions":["Find the offending cell/option: the exception lacks the coordinate, so log the value type (get_debug_type($value)) in a wrapping try/catch around save() and bisect which cell holds it.","Convert before assigning: implode arrays, cast or format objects explicitly (e.g. $model->attribute, $dt->format('Y-m-d')).","Implement __toString() on your value objects that must be writable as cell text.","If a fallback is acceptable at that call site, use StringHelper::convertToString($value, false, '') style semantics (or pre-normalize) so non-stringifiable values become '' instead of throwing."],"exampleFix":"// before\n$sheet->setCellValue('A1', $row); // $row is an array from PDO\n(new \\PhpOffice\\PhpSpreadsheet\\Writer\\Csv($sheet))->save('out.csv');\n// Unable to convert to string\n\n// after\n$sheet->setCellValue('A1', is_array($row) ? implode(';', $row) : (string) $row);\n// or give value objects a __toString() and cast explicitly","handlingStrategy":"type-guard","validationCode":"function toCellString(mixed $value): string\n{\n    return match (true) {\n        $value === null => '',\n        is_scalar($value) => (string) $value,\n        $value instanceof Stringable => (string) $value,\n        default => '', // or throw your own descriptive error\n    };\n}","typeGuard":"function isStringifiable(mixed $value): bool\n{\n    return $value === null || is_scalar($value) || $value instanceof Stringable;\n}\n\nif (!isStringifiable($cellValue)) {\n    throw new InvalidArgumentException('Cell value must be scalar or Stringable, got ' . get_debug_type($cellValue));\n}","tryCatchPattern":"try { $writer->save($path); }\ncatch (\\PhpOffice\\PhpSpreadsheet\\Exception $e) {\n    if ($e->getMessage() === 'Unable to convert to string') {\n        // value is array/plain object: log the type, fix the data source, re-save\n        throw new RuntimeException('Non-stringifiable cell value encountered during export.', 0, $e);\n    }\n    throw $e;\n}","preventionTips":["Never assign arrays or bare objects to cells — convert at assignment time (implode, format, JSON-encode if appropriate).","Give domain objects you export a __toString().","For writer options that funnel through convertToString, prefer calling it yourself with throw=false and a default when a silent fallback is acceptable."],"tags":["type-conversion","data-validation","writers","phpspreadsheet"],"backgroundTag":"invalid-type-conversion","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}