CarGuo/GSYVideoPlayer · error · ProxyCacheException

Error using file ${file} as disc cache

Error message

Error using file ${file} as disc cache

What it means

FileCache.available() returns (int) dataFile.length(); RandomAccessFile.length() rarely throws, but if the file was closed or the fd became invalid (file deleted underneath, volume unmounted), the IOException is wrapped as ProxyCacheException('Error reading length of file <path>'). It means the cache file's file descriptor is no longer usable.

Source

Thrown at gsyVideoPlayer-proxy_cache/src/main/java/com/danikula/videocache/file/FileCache.java:39

    private RandomAccessFile dataFile;

    public FileCache(File file) throws ProxyCacheException {
        this(file, new UnlimitedDiskUsage());
    }

    public FileCache(File file, DiskUsage diskUsage) throws ProxyCacheException {
        try {
            if (diskUsage == null) {
                throw new NullPointerException();
            }
            this.diskUsage = diskUsage;
            File directory = file.getParentFile();
            Files.makeDir(directory);
            boolean completed = file.exists();
            this.file = completed ? file : new File(file.getParentFile(), file.getName() + TEMP_POSTFIX);
            this.dataFile = new RandomAccessFile(this.file, completed ? "r" : "rw");
        } catch (IOException e) {
            throw new ProxyCacheException("Error using file " + file + " as disc cache", e);
        }
    }

    @Override
    public synchronized long available() throws ProxyCacheException {
        try {
            return (int) dataFile.length();
        } catch (IOException e) {
            throw new ProxyCacheException("Error reading length of file " + file, e);
        }
    }

    @Override
    public synchronized int read(byte[] buffer, long offset, int length) throws ProxyCacheException {
        try {
            dataFile.seek(offset);
            return dataFile.read(buffer, 0, length);
        } catch (IOException e) {

View on GitHub (pinned to e5d74d3aa9)

Solutions

  1. Point the proxy cache at app-internal storage that third parties cannot wipe
  2. Set maxCacheSize generously enough that the file in active use is not evicted; or fork to skip evicting the newest file
  3. On this error, evict the specific entry (clearCache for url) and restart playback so a fresh FileCache is built
  4. Avoid external removable storage for the cache directory

Example fix

// before - LRU may evict the in-use file
new Builder(ctx).maxCacheSize(64 * 1024 * 1024).build();

// after - retry path that clears the broken entry and restarts
catch (ProxyCacheException e) {
    proxyCacheServer.getHostCacheDb?? // n/a; instead:
    player.release();
    new File(cacheDir, md5(url) + ".download").delete();
    player.setUp(proxyCacheServer.getProxyUrl(url), true, headers);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!cacheFile.exists() || !cacheFile.canRead()) {
    // fd target vanished; purge entry before reading
    cacheFile.delete();
}

Try / catch

try { long avail = fileCache.available(); }
catch (ProxyCacheException e) {
    if (String.valueOf(e.getMessage()).contains("Error reading length")) {
        purgeEntryAndRestartPlayback(url); // rebuild FileCache
    } else throw e;
}

Prevention

When it happens

Trigger: The cached file (or its temp .download) was deleted while FileCache still held it - e.g. by the cache-cleaner of the proxy itself in another thread, a user storage-cleaner app, or the file living on removed external storage - and then the player requested available()/read().

Common situations: SD-card cache dirs on devices where the card is ejected; 'cleaner' apps wiping cache mid-playback; a misconfigured maxCacheSize causing the LRU trim to evict the file currently being read.

Related errors


AI-assisted analysis of CarGuo/GSYVideoPlayer@e5d74d3aa9 (2026-08-14). Data as JSON: /api/errors/8f464a99897d0883. Report an issue: GitHub.