{"record":{"id":"32d0b864f44d16ab","repo":"PHPOffice/PhpSpreadsheet","slug":"line-ending-must-be-n-unix-or-r-n-windows","errorCode":null,"errorMessage":"Line ending must be \\n (Unix) or \\r\\n (Windows)","messagePattern":"Line ending must be \\\\n \\(Unix\\) or \\\\r\\\\n \\(Windows\\)","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Writer\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Writer/Html.php","lineNumber":92,"sourceCode":"     */\n    protected string $imagesRoot = '';\n\n    /**\n     * embed images, or link to images.\n     */\n    protected bool $embedImages = false;\n\n    protected string $lineEnding = PHP_EOL;\n\n    public function getLineEnding(): string\n    {\n        return $this->lineEnding;\n    }\n\n    public function setLineEnding(string $lineEnding): self\n    {\n        if ($lineEnding != \"\\n\" && $lineEnding !== \"\\r\\n\") {\n            throw new Exception('Line ending must be \\n (Unix) or \\r\\n (Windows)');\n        }\n        $this->lineEnding = $lineEnding;\n\n        return $this;\n    }\n\n    protected bool $dataFormula = false;\n\n    public function setDataFormula(bool $dataFormula): self\n    {\n        $this->dataFormula = $dataFormula;\n\n        return $this;\n    }\n\n    protected bool $preserveFormatAndValue = false;\n\n    public function setPreserveFormatAndValue(bool $preserveFormatAndValue): self","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Writer/Html.php#L74-L110","documentation":"The HTML writer serializes output using a line-ending setting restricted to exactly two sequences: Unix LF and Windows CRLF. setLineEnding() enforces that whitelist and throws for anything else, including a lone CR, an empty string, or markup like '<br>'. The default is PHP_EOL, which is always one of the accepted values on every platform.","triggerScenarios":"setLineEnding() with a lone carriage return, an empty string, '<br>', or PHP_EOL concatenated with extra characters; passing a user-configurable newline setting straight from an export configuration screen; reusing an EOL constant list meant for CSV, which also permits a third value.","commonSituations":"Export settings UIs exposing free-text newline fields; shared newline constants between CSV and HTML writers where the CSV-legal lone CR leaks into the HTML writer.","solutions":["Pass one of the two allowed literals: LF or CRLF.","Omit the call entirely; the default PHP_EOL is always accepted.","Whitelist configuration before applying it: only accept the two exact sequences, otherwise fall back to PHP_EOL or reject the config."],"exampleFix":"// before\n$writer->setLineEnding('<br>'); // throws: only LF or CRLF allowed\n\n// after\n$writer->setLineEnding(chr(10));          // LF, Unix\n$writer->setLineEnding(chr(13) . chr(10)); // CRLF, Windows\n// or omit the call: the default PHP_EOL is always accepted","handlingStrategy":"validation","validationCode":"$eol = $config['line_ending'] ?? PHP_EOL;\n$allowed = [chr(10), chr(13) . chr(10)]; // LF, CRLF\nif (!in_array($eol, $allowed, true)) {\n    $eol = PHP_EOL; // or reject the configuration value\n}\n$writer->setLineEnding($eol);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Whitelist newline settings to the two exact sequences before applying them.","Rely on the default PHP_EOL unless a specific output format requires CRLF.","Do not share EOL constant lists with CSV code, which permits a lone CR."],"tags":["phpspreadsheet","writer","html","line-endings","configuration"],"backgroundTag":"invalid-configuration-value","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}