{"record":{"id":"172629ab8c9ae497","repo":"CarGuo/GSYVideoPlayer","slug":"error-closing-file-s","errorCode":null,"errorMessage":"Error closing file %s","messagePattern":"Error closing file (.+?)","errorType":"exception","errorClass":"ProxyCacheException","httpStatus":null,"severity":"error","filePath":"gsyVideoPlayer-proxy_cache/src/main/java/com/danikula/videocache/file/FileCache.java","lineNumber":83,"sourceCode":"        try {\n            if (isCompleted()) {\n                throw new ProxyCacheException(\"Error append cache: cache file \" + file + \" is completed!\");\n            }\n            dataFile.seek(available());\n            dataFile.write(data, 0, length);\n        } catch (IOException e) {\n            String format = \"Error writing %d bytes to %s from buffer with size %d\";\n            throw new ProxyCacheException(String.format(format, length, dataFile, data.length), e);\n        }\n    }\n\n    @Override\n    public synchronized void close() throws ProxyCacheException {\n        try {\n            dataFile.close();\n            diskUsage.touch(file);\n        } catch (IOException e) {\n            throw new ProxyCacheException(\"Error closing file \" + file, e);\n        }\n    }\n\n    @Override\n    public synchronized void complete() throws ProxyCacheException {\n        if (isCompleted()) {\n            return;\n        }\n\n        close();\n        String fileName = file.getName().substring(0, file.getName().length() - TEMP_POSTFIX.length());\n        File completedFile = new File(file.getParentFile(), fileName);\n        boolean renamed = file.renameTo(completedFile);\n        if (!renamed) {\n            throw new ProxyCacheException(\"Error renaming file \" + file + \" to \" + completedFile + \" for completion!\");\n        }\n        file = completedFile;\n        try {","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/CarGuo/GSYVideoPlayer/blob/e5d74d3aa9d7fb1393a879e33ee380f8f41354f1/gsyVideoPlayer-proxy_cache/src/main/java/com/danikula/videocache/file/FileCache.java#L65-L101","documentation":"FileCache.complete closes the temp file and renameTo()s name.download to name. If rename fails (returns false), it throws ProxyCacheException('Error renaming file X to Y for completion!'). Rename fails across filesystems, when the target exists, or when the file is still open/locked by another handle - leaving the cache permanently in .download state for that url.","triggerScenarios":"A completed file with the target name already exists (previous run crashed after rename but before cleanup); the temp file is held open by another fd (second reader); directory permissions changed; vendor filesystems that fail rename of open files.","commonSituations":"App killed mid-completion leaving both .download and final file; two proxy instances over one cache dir; some OEM/FUSE filesystems (scoped-storage emulation) rejecting renames of open files; cache dir on sdcardfs with quirky rename semantics.","solutions":["Ensure exactly one HttpProxyCacheServer per cache directory and process","On this error, delete the stale .download (and conflicting final file) for that url and re-cache","Run a one-time cleanup at app start: remove leftover *.download files older than the previous session","Keep the cache dir on internal storage where rename semantics are reliable"],"exampleFix":"// before - let the exception kill the caching thread\n\n// after - startup cleanup of half-completed entries\nFile[] stale = cacheDir.listFiles((d, n) -> n.endsWith(\".download\"));\nif (stale != null) for (File f : stale) f.delete();","handlingStrategy":"fallback","validationCode":"File completed = new File(cacheDir, md5(url));\nFile temp = new File(cacheDir, md5(url) + \".download\");\nif (completed.exists() && temp.exists()) {\n    temp.delete(); // resolve rename collision before completion runs\n}","typeGuard":null,"tryCatchPattern":"catch (ProxyCacheException e) {\n    if (String.valueOf(e.getMessage()).contains(\"Error renaming\")) {\n        new File(cacheDir, md5(url) + \".download\").delete(); // purge, will re-cache next time\n    } else throw e;\n}","preventionTips":["One proxy instance per cache directory","Clean leftover .download files at app start","Keep cache dir on internal storage with reliable rename semantics"],"tags":["io","rename","filesystem","crash-recovery","proxy-cache"],"backgroundTag":null,"analyzedSha":"e5d74d3aa9d7fb1393a879e33ee380f8f41354f1","analyzedAt":"2026-08-14T11:56:11.997Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}