{"id":"ee011038c8a7e7a7","repo":"pytest-dev/pytest","slug":"ext-must-not-be-none","errorCode":null,"errorMessage":"ext must not be None","messagePattern":"ext must not be None","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/pytester.py","lineNumber":769,"sourceCode":"\n    def chdir(self) -> None:\n        \"\"\"Cd into the temporary directory.\n\n        This is done automatically upon instantiation.\n        \"\"\"\n        self._monkeypatch.chdir(self.path)\n\n    def _makefile(\n        self,\n        ext: str,\n        lines: Sequence[Any | bytes],\n        files: Mapping[str, _FileContent],\n        encoding: str = \"utf-8\",\n    ) -> Path:\n        items = list(files.items())\n\n        if ext is None:\n            raise TypeError(\"ext must not be None\")\n\n        if ext and not ext.startswith(\".\"):\n            raise ValueError(\n                f\"pytester.makefile expects a file extension, try .{ext} instead of {ext}\"\n            )\n\n        def to_text(s: Any | bytes) -> str:\n            return s.decode(encoding) if isinstance(s, bytes) else str(s)\n\n        if lines:\n            source = \"\\n\".join(to_text(x) for x in lines)\n            basename = self._name\n            items.insert(0, (basename, source))\n\n        ret = None\n        for basename, value in items:\n            p = self.path.joinpath(basename).with_suffix(ext)\n            p.parent.mkdir(parents=True, exist_ok=True)","sourceCodeStart":751,"sourceCodeEnd":787,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/pytester.py#L751-L787","documentation":"Raised by Pytester._makefile (the backend of makefile/makepyfile) when the ext argument is None. makefile requires a concrete file extension string to construct the output filename via Path.with_suffix(ext), and None is not a valid suffix. This is a hard precondition check before any file is written.","triggerScenarios":"Calling pytester.makefile(None, ...) explicitly, or a wrapper/helper that forwards a None ext, or calling makepyfile internals that default ext to None for a package-less layout.","commonSituations":"Programmatically building the ext argument from a config value that resolved to None; copy-pasting a makepyfile call pattern into a custom makefile invocation; a refactor that changed the default of a helper to None.","solutions":["Pass a concrete extension including the dot, e.g. '.py' or '.txt'.","Default ext to '.py' in your own helper when the source value is None.","Use makepyfile(...) instead of makefile when you always want Python files, since it supplies the extension for you."],"exampleFix":"// before\npytester.makefile(ext, foo=source)  # ext may be None\n// after\npytester.makefile(ext or \".py\", foo=source)","handlingStrategy":"validation","validationCode":"def safe_makefile(pytester, ext, **kw):\n    if ext is None:\n        ext = \".py\"\n    return pytester.makefile(ext, **kw)","typeGuard":"def is_valid_ext(ext: object) -> bool:\n    return isinstance(ext, str)","tryCatchPattern":null,"preventionTips":["Never pass None as ext; default to '.py' in helpers.","Prefer makepyfile() for Python files."],"tags":["pytester","file-creation","validation"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}