{"record":{"id":"5dd686796081a14c","repo":"Aider-AI/aider","slug":"invalid-line-endings-value-line-endings-must-b","errorCode":null,"errorMessage":"Invalid line_endings value: {line_endings}. Must be one of: {', '.join(valid_line_endings)}","messagePattern":"Invalid line_endings value: (.+?)\\. Must be one of: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aider/io.py","lineNumber":326,"sourceCode":"        self.yes = yes\n\n        self.input_history_file = input_history_file\n        if self.input_history_file:\n            try:\n                Path(self.input_history_file).parent.mkdir(parents=True, exist_ok=True)\n            except (PermissionError, OSError) as e:\n                self.tool_warning(f\"Could not create directory for input history: {e}\")\n                self.input_history_file = None\n        self.llm_history_file = llm_history_file\n        if chat_history_file is not None:\n            self.chat_history_file = Path(chat_history_file)\n        else:\n            self.chat_history_file = None\n\n        self.encoding = encoding\n        valid_line_endings = {\"platform\", \"lf\", \"crlf\"}\n        if line_endings not in valid_line_endings:\n            raise ValueError(\n                f\"Invalid line_endings value: {line_endings}. \"\n                f\"Must be one of: {', '.join(valid_line_endings)}\"\n            )\n        self.newline = (\n            None if line_endings == \"platform\" else \"\\n\" if line_endings == \"lf\" else \"\\r\\n\"\n        )\n        self.dry_run = dry_run\n\n        current_time = datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        self.append_chat_history(f\"\\n# aider chat started at {current_time}\\n\\n\")\n\n        self.prompt_session = None\n        self.is_dumb_terminal = is_dumb_terminal()\n\n        if self.is_dumb_terminal:\n            self.pretty = False\n            fancy_input = False\n","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/Aider-AI/aider/blob/5dc9490bb35f9729ef2c95d00a19ccd30c26339c/aider/io.py#L308-L344","documentation":"InputOutput.__init__ in aider/io.py validates the line_endings constructor argument against a whitelist {\"platform\", \"lf\", \"crlf\"}. Any other value — including None (unless you match the exact strings), typos like 'CRLF', 'windows', or 'auto' — raises ValueError at construction time, before any I/O happens. The chosen value is later mapped to self.newline (None for platform, \\n for lf, \\r\\n for crlf) which controls how chat/input history files are written.","triggerScenarios":"Instantiating InputOutput(line_endings=...) with a string outside the set {'platform','lf','crlf'}. Typical offenders: 'CRLF' (uppercase), 'LF', '\\r\\n', 'windows', 'unix', 'native', or passing an int/None where a string is expected. It raises immediately in __init__, so the failure occurs at object creation, not during file writes.","commonSituations":"Programmatically embedding aider's IO class in another tool and deriving line_endings from a config enum (e.g. LineEndings.CRLF.name yielding 'CRLF') or from platform.system() output ('Windows' instead of 'crlf'). Interactive CLI users rarely hit it because aider's own args pass one of the three valid literals.","solutions":["Pass exactly one of the three accepted strings: 'platform' (use OS default), 'lf', or 'crlf'.","If the value comes from user config, normalize it first: strip whitespace and lowercase it, then check membership before constructing InputOutput.","Map platform names explicitly: 'Windows' -> 'crlf', 'Linux'/'Darwin' -> 'lf', or just use 'platform' to defer to the OS default."],"exampleFix":"# before\nio = InputOutput(line_endings=\"CRLF\")  # ValueError: Invalid line_endings value\n\n# after\nraw = \"CRLF\".strip().lower()\nline_endings = raw if raw in {\"platform\", \"lf\", \"crlf\"} else \"platform\"\nio = InputOutput(line_endings=line_endings)","handlingStrategy":"validation","validationCode":"VALID = {\"platform\", \"lf\", \"crlf\"}\n\ndef make_io(line_endings):\n    key = str(line_endings).strip().lower()\n    if key not in VALID:\n        raise ValueError(f\"line_endings must be one of {sorted(VALID)}, got {line_endings!r}\")\n    from aider.io import InputOutput\n    return InputOutput(line_endings=key)","typeGuard":"def is_valid_line_endings(v) -> bool:\n    return isinstance(v, str) and v.strip().lower() in {\"platform\", \"lf\", \"crlf\"}","tryCatchPattern":"try:\n    io = InputOutput(line_endings=le)\nexcept ValueError as e:\n    if \"Invalid line_endings\" in str(e):\n        io = InputOutput(line_endings=\"platform\")  # safe default\n    else:\n        raise","preventionTips":["Centralize the normalization (lowercase + membership check) at whatever boundary accepts user config.","Map platform identifiers explicitly ('Windows'->'crlf', else 'lf') or just use 'platform'.","Write a unit test asserting every config enum value you support maps into {'platform','lf','crlf'}."],"tags":["validation","configuration","line-endings","constructor","aider"],"backgroundTag":null,"analyzedSha":"5dc9490bb35f9729ef2c95d00a19ccd30c26339c","analyzedAt":"2026-08-15T05:40:10.498Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}