{"record":{"id":"b7a49a5b7b83734b","repo":"RustPython/RustPython","slug":"unclosed-file-repr","errorCode":null,"errorMessage":"unclosed file {repr}","messagePattern":"unclosed file (.+?)","errorType":"console","errorClass":"ResourceWarning","httpStatus":null,"severity":"warning","filePath":"crates/vm/src/stdlib/_io.rs","lineNumber":6064,"sourceCode":"        fn __getstate__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult {\n            Err(vm.new_type_error(format!(\"cannot pickle '{}' instances\", zelf.class().name())))\n        }\n\n        /// fileio_dealloc_warn in Modules/_io/fileio.c\n        #[pymethod(name = \"_dealloc_warn\")]\n        fn _dealloc_warn_method(zelf: &Py<Self>, source: PyObjectRef, vm: &VirtualMachine) {\n            Self::dealloc_warn(zelf, source, vm);\n        }\n    }\n\n    impl FileIO {\n        /// Issue ResourceWarning if fd is still open and closefd is true.\n        fn dealloc_warn(zelf: &Py<Self>, source: PyObjectRef, vm: &VirtualMachine) {\n            if zelf.fd.load() >= 0 && zelf.closefd.load() {\n                let repr = source\n                    .repr(vm)\n                    .map_or_else(|_| Wtf8Buf::from(\"<file>\"), |s| s.as_wtf8().to_owned());\n                if let Err(e) = crate::stdlib::_warnings::warn(\n                    vm.ctx.exceptions.resource_warning,\n                    format!(\"unclosed file {repr}\"),\n                    1,\n                    vm,\n                ) {\n                    vm.run_unraisable(e, None, zelf.as_object().to_owned());\n                }\n            }\n        }\n    }\n\n    impl Destructor for FileIO {\n        fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {\n            if let Some(fileio) = zelf.downcast_ref::<Self>() {\n                fileio.finalizing.store(true);\n            }\n            iobase_finalize(zelf, vm);\n            Ok(())","sourceCodeStart":6046,"sourceCodeEnd":6082,"githubUrl":"https://github.com/RustPython/RustPython/blob/5dc83d997e635e8ddce1af1a989299d241389e17/crates/vm/src/stdlib/_io.rs#L6046-L6082","documentation":"ResourceWarning emitted from FileIO's dealloc hook when the object is dropped while its fd is still >= 0 and closefd is true — i.e. the file was never close()d and cleanup fell to the garbage collector. File descriptors are a finite process-global resource, so both CPython and RustPython warn at destruction to make the leak visible. If raising the warning itself fails, it is routed through run_unraisable.","triggerScenarios":"open()/io.FileIO without close(); exceptions that skip the close() call; storing file objects in caches/containers and dropping them later; reference cycles that delay collection. Usually observed only when GC actually runs, or under -X dev / -Wd.","commonSituations":"Long-running servers gradually exhausting fds; scripts that open many files in a loop; test suites that fail intermittently with 'Too many open files' after warnings are enabled.","solutions":["Use a with statement: with open(p) as f: ...","Use try/finally with close() when a with block does not fit the control flow","Give every cached file object an owner responsible for closing it","Run tests with python -X dev or -W error::ResourceWarning so leaks fail fast"],"exampleFix":"# before\nf = open(\"log.txt\", \"rb\")\ndata = f.read()\n\n# after\nwith open(\"log.txt\", \"rb\") as f:\n    data = f.read()","handlingStrategy":"try-catch","validationCode":"import gc, warnings\n\ndef assert_no_unclosed_files(stage):\n    gc.collect()\n    with warnings.catch_warnings(record=True) as caught:\n        warnings.simplefilter(\"always\", ResourceWarning)\n        gc.collect()\n    leaks = [str(w.message) for w in caught if \"unclosed file\" in str(w.message)]\n    assert not leaks, f\"{stage}: {leaks}\"","typeGuard":null,"tryCatchPattern":"import warnings\nwith warnings.catch_warnings():\n    warnings.simplefilter(\"error\", ResourceWarning)\n    code_under_test()  # raises ResourceWarning as an exception at GC time","preventionTips":["Open files only via with statements in new code","Give cached/stored file objects a designated owner that closes them","Run test suites under python -X dev so leaks fail instead of warning quietly"],"tags":["io","fileio","resource-warning","fd-leak"],"backgroundTag":"unclosed-file-resource-warning","analyzedSha":"5dc83d997e635e8ddce1af1a989299d241389e17","analyzedAt":"2026-08-17T08:14:46.185Z","contentChangedAt":"2026-08-17T08:14:46.185Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}