{"record":{"id":"e9de595ceb479bcb","repo":"juicedata/juicefs","slug":"invalid-whence-whence-should-be-os-seek-set","errorCode":null,"errorMessage":"invalid whence ({whence}, should be {os.SEEK_SET}, {os.SEEK_CUR} or {os.SEEK_END})","messagePattern":"invalid whence \\((.+?), should be (.+?), (.+?) or (.+?)\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdk/python/juicefs/juicefs/juicefs.py","lineNumber":564,"sourceCode":"            raise io.UnsupportedOperation('not writable')\n\n        if not data:\n            return 0\n        if self.append:\n            self.off = self.length\n        n = self.lib.jfs_pwrite(c_int64(_tid()), c_int32(self.fd), data, c_int32(len(data)), c_int64(self.off))\n        self.off += n\n        if self.off > self.length:\n            self.length = self.off\n        return n\n\n    def seek(self, offset, whence=0):\n        \"\"\"Set the stream position to the given byte offset.\n        offset is interpreted relative to the position indicated by whence.\n        The default value for whence is SEEK_SET.\"\"\"\n        self._check_closed()\n        if whence not in (os.SEEK_SET, os.SEEK_CUR, os.SEEK_END):\n            raise ValueError(f'invalid whence ({whence}, should be {os.SEEK_SET}, {os.SEEK_CUR} or {os.SEEK_END})')\n        if whence == os.SEEK_SET:\n            self.off = offset\n        elif whence == os.SEEK_CUR:\n            self.off += offset\n        else:\n            self.off = self.length + offset\n        return self.off\n\n    def tell(self):\n        \"\"\"Return the current stream position.\"\"\"\n        self._check_closed()\n        return self.off\n\n    def truncate(self, size=None):\n        \"\"\"Truncate the file to at most size bytes.\n        Size defaults to the current file position, as returned by tell().\"\"\"\n        self._check_closed()\n        if not self.writable():","sourceCodeStart":546,"sourceCodeEnd":582,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/sdk/python/juicefs/juicefs/juicefs.py#L546-L582","documentation":"Raised by JuiceFile.seek in the Python SDK when the whence argument is not one of os.SEEK_SET (0), os.SEEK_CUR (1), or os.SEEK_END (2). The seek offset cannot be interpreted without a valid reference point, so the bad whence is rejected before any jfs call.","triggerScenarios":"Calling f.seek(offset, 3) or f.seek(offset, 'cur'); passing a string whence copied from another API; computing whence dynamically and producing a bad value.","commonSituations":"Porting from APIs that accept string whence ('SET'/'CUR'/'END'); off-by-one or None whence from config; wrapping seek in a helper with an unvalidated parameter.","solutions":["Pass one of os.SEEK_SET, os.SEEK_CUR, os.SEEK_END (or 0/1/2)","Default to f.seek(offset) which uses whence=0 (SEEK_SET)","Validate/normalize the whence parameter before calling seek"],"exampleFix":"// before\nf.seek(100, 'cur')\n// after\nimport os\nf.seek(100, os.SEEK_CUR)","handlingStrategy":"validation","validationCode":"import os\nVALID_WHENCE = (os.SEEK_SET, os.SEEK_CUR, os.SEEK_END)\nif whence not in VALID_WHENCE:\n    whence = os.SEEK_SET","typeGuard":"def valid_whence(w) -> bool:\n    import os\n    return w in (os.SEEK_SET, os.SEEK_CUR, os.SEEK_END)","tryCatchPattern":"try:\n    f.seek(off, whence)\nexcept ValueError:\n    f.seek(off)","preventionTips":["Always use os.SEEK_* constants, never literals or strings","Default to SEEK_SET unless relative positioning is needed"],"tags":["python","valueerror","seek","whence"],"backgroundTag":"invalid-enum-value","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}