{"record":{"id":"bfd59c9aa818b64d","repo":"D4Vinci/Scrapling","slug":"unknown-file-type-filename-must-end-with-md","errorCode":null,"errorMessage":"Unknown file type: filename must end with '.md', '.html', or '.txt'","messagePattern":"Unknown file type: filename must end with '\\.md', '\\.html', or '\\.txt'","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scrapling/core/shell.py","lineNumber":667,"sourceCode":"                            \"\\t\",\n                            \" \",\n                        ):\n                            # Remove consecutive white-spaces\n                            txt_content = TextHandler(re_sub(f\"[{s}]+\", s, txt_content))\n                        yield txt_content\n            yield \"\"\n\n    @classmethod\n    def write_content_to_file(\n        cls, page: Selector, filename: str, css_selector: Optional[str] = None, main_content_only: bool = False\n    ) -> None:\n        \"\"\"Write a Selector's content to a file\"\"\"\n        if not page or not isinstance(page, Selector):  # pragma: no cover\n            raise TypeError(\"Input must be of type `Selector`\")\n        elif not filename or not isinstance(filename, str) or not filename.strip():\n            raise ValueError(\"Filename must be provided\")\n        elif not filename.endswith((\".md\", \".html\", \".txt\")):\n            raise ValueError(\"Unknown file type: filename must end with '.md', '.html', or '.txt'\")\n        else:\n            with open(filename, \"w\", encoding=page.encoding) as f:\n                extension = filename.split(\".\")[-1]\n                f.write(\n                    \"\".join(\n                        cls._extract_content(\n                            page,\n                            cls._extension_map[extension],\n                            css_selector=css_selector,\n                            main_content_only=main_content_only,\n                        )\n                    )\n                )\n","sourceCodeStart":649,"sourceCodeEnd":681,"githubUrl":"https://github.com/D4Vinci/Scrapling/blob/5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f/scrapling/core/shell.py#L649-L681","documentation":"write_content_to_file dispatches on the filename's extension: only '.md', '.html', and '.txt' are mapped (to markdown, html, and text extraction respectively via _extension_map). Any other extension (or no extension) raises ValueError listing the allowed set, because there would be no extraction strategy to apply.","triggerScenarios":"Calling write_content_to_file(page, 'out.docx'), 'page.json', 'archive.tar.gz', or 'output' (no extension). The check is on the literal suffix, so '.Markdown' or '.MD' (case-sensitive) also fail.","commonSituations":"Generating filenames from content type or site names (e.g. '.pdf' assumed supported), uppercase extensions from Windows-origin paths, or extension stripped by path handling.","solutions":["Use one of the three exact extensions: .md, .html, .txt","Normalize case: filename = filename.lower() before the call if sources may use .MD/.HTML","If you need another format, write to .html/.md/.txt and convert with a dedicated tool afterwards"],"exampleFix":"# before\nConvertor.write_content_to_file(page, 'report.PDF')\n\n# after\nConvertor.write_content_to_file(page, 'report.md')","handlingStrategy":"validation","validationCode":"EXTS = ('.md', '.html', '.txt')\nfilename = filename.lower()\nif not filename.endswith(EXTS):\n    filename += '.md'  # or reject explicitly","typeGuard":"from typing import Any\n\ndef has_supported_ext(filename: Any) -> bool:\n    return isinstance(filename, str) and filename.lower().endswith(('.md', '.html', '.txt'))","tryCatchPattern":null,"preventionTips":["Normalize filename case before the call","Build output names from a fixed allowlist of extensions"],"tags":["shell","validation","file-output","extension"],"backgroundTag":null,"analyzedSha":"5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f","analyzedAt":"2026-08-14T22:23:09.440Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}