{"record":{"id":"ad95464f5a17f47d","repo":"juicedata/juicefs","slug":"cannot-serialise-open-write-mode-local-file","errorCode":null,"errorMessage":"Cannot serialise open write-mode local file","messagePattern":"Cannot serialise open write-mode local file","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdk/python/juicefs/juicefs/spec.py","lineNumber":256,"sourceCode":"        return self.f.read(end - start)\n\n    def __setstate__(self, state):\n        self.f = None\n        loc = state.pop(\"loc\", None)\n        self.__dict__.update(state)\n        if \"r\" in state[\"mode\"]:\n            self.f = None\n            self._open()\n            self.f.seek(loc)\n\n    def __getstate__(self):\n        d = self.__dict__.copy()\n        d.pop(\"f\")\n        if \"r\" in self.mode:\n            d[\"loc\"] = self.f.tell()\n        else:\n            if not self.f.closed:\n                raise ValueError(\"Cannot serialise open write-mode local file\")\n        return d\n\n    def commit(self):\n        if self.autocommit:\n            raise RuntimeError(\"Can only commit if not already set to autocommit\")\n        self.fs.fs.rename(self.temp, self.path)\n\n    def discard(self):\n        if self.autocommit:\n            raise RuntimeError(\"Can only commit if not already set to autocommit\")\n        self.fs.fs.remove(self.temp)\n\n    def tell(self):\n        return self.f.tell()\n\n    def seek(self, loc, whence=0):\n        return self.f.seek(loc, whence)\n","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/sdk/python/juicefs/juicefs/spec.py#L238-L274","documentation":"LocalFile.__getstate__ (used for pickling/serializing the handle) refuses to serialize a write-mode local file whose underlying temp file is still open, raising ValueError('Cannot serialise open write-mode local file'). Write-mode files carry uncommitted temp state that cannot be transferred across processes.","triggerScenarios":"Pickling a LocalFile opened for writing ('w'/'wb') before close()/commit(); using multiprocessing or distributed frameworks (e.g. Dask) that pickle open write handles; copy.copy/deep_copy of such a handle.","commonSituations":"Passing open write handles to worker processes; serializing file objects in task queues; checkpointing code that stores file objects in pickled state.","solutions":["Close or commit the file before pickling","Open the file again inside the target process instead of transferring the handle","Open in read mode ('r') if the handle must be pickled, since read-mode files serialize their location","Subclass and override __getstate__ only if you can guarantee the temp file semantics yourself"],"exampleFix":"// before\nf = fs.open('/mnt/jfs/out', 'wb')\npickle.dumps(f)  # ValueError\n// after\nf = fs.open('/mnt/jfs/out', 'wb')\nf.commit()   # or f.close()\npickle.dumps(f)\n# or reopen in worker:\nworker_fn(path='/mnt/jfs/out')","handlingStrategy":"validation","validationCode":"if 'w' in f.mode and not f.f.closed:\n    f.commit()  # or f.close() before pickling\npickle.dumps(f)","typeGuard":"def picklable_file(f) -> bool:\n    return 'r' in f.mode or f.f.closed","tryCatchPattern":"try:\n    state = pickle.dumps(f)\nexcept ValueError as e:\n    if 'serialise open write-mode' in str(e):\n        f.close(); state = pickle.dumps(f)","preventionTips":["Close/commit write-mode local files before pickling","Pass paths, not handles, across process boundaries"],"tags":["python","valueerror","pickle","localfile","serialization"],"backgroundTag":"json-serialization-failed","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}