{"record":{"id":"c49fc8557b9baf4b","repo":"CarGuo/GSYVideoPlayer","slug":"error-reading-length-of-file-file","errorCode":null,"errorMessage":"Error reading length of file ${file}","messagePattern":"Error reading length of file (.+?)","errorType":"exception","errorClass":"ProxyCacheException","httpStatus":null,"severity":"error","filePath":"gsyVideoPlayer-proxy_cache/src/main/java/com/danikula/videocache/file/FileCache.java","lineNumber":48,"sourceCode":"                throw new NullPointerException();\n            }\n            this.diskUsage = diskUsage;\n            File directory = file.getParentFile();\n            Files.makeDir(directory);\n            boolean completed = file.exists();\n            this.file = completed ? file : new File(file.getParentFile(), file.getName() + TEMP_POSTFIX);\n            this.dataFile = new RandomAccessFile(this.file, completed ? \"r\" : \"rw\");\n        } catch (IOException e) {\n            throw new ProxyCacheException(\"Error using file \" + file + \" as disc cache\", e);\n        }\n    }\n\n    @Override\n    public synchronized long available() throws ProxyCacheException {\n        try {\n            return (int) dataFile.length();\n        } catch (IOException e) {\n            throw new ProxyCacheException(\"Error reading length of file \" + file, e);\n        }\n    }\n\n    @Override\n    public synchronized int read(byte[] buffer, long offset, int length) throws ProxyCacheException {\n        try {\n            dataFile.seek(offset);\n            return dataFile.read(buffer, 0, length);\n        } catch (IOException e) {\n            String format = \"Error reading %d bytes with offset %d from file[%d bytes] to buffer[%d bytes]\";\n            throw new ProxyCacheException(String.format(format, length, offset, available(), buffer.length), e);\n        }\n    }\n\n    @Override\n    public synchronized void append(byte[] data, int length) throws ProxyCacheException {\n        try {\n            if (isCompleted()) {","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/CarGuo/GSYVideoPlayer/blob/e5d74d3aa9d7fb1393a879e33ee380f8f41354f1/gsyVideoPlayer-proxy_cache/src/main/java/com/danikula/videocache/file/FileCache.java#L30-L66","documentation":"FileCache.read does dataFile.seek(offset) then read(buffer, 0, length); any IOException (seek past EOF on a truncated temp file, closed RandomAccessFile, deleted file) is formatted into a message showing requested length, offset, available bytes, and buffer size - deliberately diagnostic for the classic 'cache file shorter than expected' bug.","triggerScenarios":"Player requests bytes at an offset beyond what the .download temp file holds because SourceInfo advertised a length larger than actually cached (server lied about Content-Length, or a partial download was recorded as longer); or the fd was closed/deleted concurrently.","commonSituations":"Servers reporting gzip-encoded Content-Length while the proxy stores decoded bytes (length mismatch); seek into a region never downloaded after a network gap; multi-threaded download interleaving with the proxy's single-writer assumption.","solutions":["Ensure the origin sends correct Content-Length for range requests (no gzip on media, Accept-Encoding identity)","On this error, delete the broken cache entry and restart playback so SourceInfo/FileCache are rebuilt","Do not run a parallel downloader on the same cache files the proxy owns","Verify the offset the player seeks to is within cached bounds before reading (validation wrapper)"],"exampleFix":"// before - read blindly at requested offset\nint read = cache.read(buffer, offset, length);\n\n// after - validate against available bytes\nlong avail = cache.available();\nif (offset >= avail) {\n    throw new ProxyCacheException(\"Offset \" + offset + \" beyond cached \" + avail + \" - wait or re-open source\");\n}\nint read = cache.read(buffer, offset, (int) Math.min(length, avail - offset));","handlingStrategy":"validation","validationCode":"long avail = cache.available();\nif (offset < 0 || offset >= avail) {\n    throw new IllegalArgumentException(\"read offset \" + offset + \" outside cached range [0,\" + avail + \")\");\n}\nint len = (int) Math.min(length, avail - offset);","typeGuard":null,"tryCatchPattern":"catch (ProxyCacheException e) {\n    if (String.valueOf(e.getMessage()).contains(\"Error reading\") && e.getMessage().contains(\"bytes with offset\")) {\n        purgeEntryAndRestartPlayback(url); // truncated/mismatched cache file\n    } else throw e;\n}","preventionTips":["Ensure the origin sends correct Content-Length (no gzip on media)","Validate offsets against available() before reading","Delete mismatched .download files rather than reusing them"],"tags":["io","offset","content-length","seek","proxy-cache"],"backgroundTag":null,"analyzedSha":"e5d74d3aa9d7fb1393a879e33ee380f8f41354f1","analyzedAt":"2026-08-14T11:56:11.997Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}