CarGuo/GSYVideoPlayer · warning · ProxyCacheException
Error reading %d bytes with offset %d from file[%d bytes] to
Error message
Error reading %d bytes with offset %d from file[%d bytes] to buffer[%d bytes]
What it means
FileCache.append refuses to write once isCompleted() is true (file renamed from .download to final, opened read-only). Throwing here guards the invariant that a completed cache file is immutable; it fires when the source reader tries to add bytes after completion was already signaled - usually a race or a double-pump in the caching loop.
Source
Thrown at gsyVideoPlayer-proxy_cache/src/main/java/com/danikula/videocache/file/FileCache.java:59
}
@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) {
String format = "Error reading %d bytes with offset %d from file[%d bytes] to buffer[%d bytes]";
throw new ProxyCacheException(String.format(format, length, offset, available(), buffer.length), e);
}
}
@Override
public synchronized void append(byte[] data, int length) throws ProxyCacheException {
try {
if (isCompleted()) {
throw new ProxyCacheException("Error append cache: cache file " + file + " is completed!");
}
dataFile.seek(available());
dataFile.write(data, 0, length);
} catch (IOException e) {
String format = "Error writing %d bytes to %s from buffer with size %d";
throw new ProxyCacheException(String.format(format, length, dataFile, data.length), e);
}
}
@OverrideView on GitHub (pinned to e5d74d3aa9)
Solutions
- Reuse one HttpProxyCacheServer and one player per url; avoid starting two concurrent playbacks of the same url during a retry storm
- On this error, simply discard it in logs - the file is already fully cached and usable
- If it recurs in your fork, add a state check (isCompleted) before entering the append path in your reader loop
Example fix
// before - unconditional append
fileCache.append(data, read);
// after - guard
if (!fileCache.isCompleted()) {
fileCache.append(data, read);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!fileCache.isCompleted()) {
fileCache.append(data, read);
} Type guard
boolean canAppend = !fileCache.isCompleted(); // guard before append
Try / catch
catch (ProxyCacheException e) {
if (String.valueOf(e.getMessage()).contains("is completed")) {
// benign: file already fully cached, drop the write
Log.d(TAG, "append after completion ignored");
} else throw e;
} Prevention
- One player/proxy session per url at a time
- Check isCompleted() before writing
- Treat this specific message as benign log noise
When it happens
Trigger: Two paths append to the same FileCache after complete() ran: e.g. ProxyCache.readSource retrying after completion, or two proxy requests for the same url sharing a cache entry where the second writer outlives the first's completion.
Common situations: Concurrent playback of the same url in two players with a shared proxy; race between the completion path (close + rename) and a lingering reader thread after an error/retry cycle. Rare in normal single-player usage.
Related errors
- Error renaming file %s to %s for completion!
- Reading source ${sourceInfo.url} is interrupted
- Error reading source ${errorsCount} times
- Error using file ${file} as disc cache
- Error reading length of file ${file}
AI-assisted analysis of CarGuo/GSYVideoPlayer@e5d74d3aa9 (2026-08-14).
Data as JSON: /api/errors/6eb0c23e95e5ea6a.
Report an issue: GitHub.