lingochamp/FileDownloader · error · NoFieldException
getLargeSofarBytes
Error message
getLargeSofarBytes
What it means
MessageSnapshot's abstract base class implements getLargeSofarBytes() to throw NoFieldException (an IllegalStateException). Only concrete snapshot subclasses that actually carry a 'sofar bytes' field (e.g. LargeMessageSnapshot.ProgressMessageSnapshot, ConnectedMessageSnapshot) override it with a real value. The exception means the accessor was called on a snapshot whose download status has no such field (e.g. a StartedMessageSnapshot or a WarnMessageSnapshot), signaling a logic bug in whoever consumed the snapshot.
Solutions
- Check snapshot.getStatus() before reading progress fields; only call getLargeSofarBytes() on progress/connected (large-file) snapshots.
- Fix the internal caller (update or message-conversion code) to pick fields appropriate to the snapshot's concrete class instead of unconditionally querying all accessors.
- If you need byte counts regardless of status, store the last valid progress values from the progress callback and use those when the status is not progress.
- Ensure the correct snapshot subclass is created via MessageSnapshot.CREATOR for the status rather than constructing a base/subclass that lacks the field.
Example fix
// before
@Override public void progress(FileDownloadTask task, int sofar, int total) {
long sofarBytes = task.getMessageSnapshot().getLargeSofarBytes();
}
// after
@Override public void progress(FileDownloadTask task, int sofar, int total) {
MessageSnapshot snap = task.getMessageSnapshot();
long sofarBytes = snap.isLargeFile()
? snap.getLargeSofarBytes()
: snap.getSmallSofarBytes();
} Defensive patterns
Strategy: type-guard
Validate before calling
// Safe only for large-file snapshots with byte fields
public static boolean hasLargeProgress(IMessageSnapshot s) {
return s.isLargeFile()
&& (s.getStatus() == FileDownloadStatus.progress
|| s.getStatus() == FileDownloadStatus.connected);
} Type guard
public static boolean canReadLargeSofar(IMessageSnapshot s) {
return s.isLargeFile()
&& (s.getStatus() == FileDownloadStatus.progress
|| s.getStatus() == FileDownloadStatus.connected);
}
// usage: if (canReadLargeSofar(snap)) long sofar = snap.getLargeSofarBytes(); Try / catch
long sofar;
try {
sofar = snapshot.getLargeSofarBytes();
} catch (IllegalStateException e) {
// NoFieldException: field absent for this status
sofar = lastKnownSofar; // fallback to cached progress
} Prevention
- Always switch on getStatus() before reading any IMessageSnapshot accessor.
- Use isLargeFile() to pick the small vs large accessor pair.
- Never cache snapshots across status changes and query them later; copy out the values you need when the callback fires.
- Cover each listener callback with tests that exercise every download status.
When it happens
Trigger: Calling IMessageSnapshot.getLargeSofarBytes() (directly or via a FileDownloadListener block) on a MessageSnapshot for a status that does not store progress bytes, such as FileDownloadStatus.started, warn, pending (small), completed, or error snapshots.
Common situations: A FileDownloadListener callback reads sofar/total bytes without checking getStatus() first; code that caches a MessageSnapshot across status changes and later reads progress fields from it; custom message routing code (like the internal update()/handoverMessage paths) forwarding snapshots of the wrong status; upgrades where a previously overridden method became a throwing base-class default.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- getLargeTotalBytes
- getSmallSofarBytes
- getSmallTotalBytes
- isReusedDownloadedFile
- fetched length[ ] != content length[ ], range[ , ) offset[…
AI-assisted analysis of lingochamp/FileDownloader@6237a8cac1 (2026-09-08).
Data as JSON: /api/errors/282ef709bd4d625b.
Report an issue: GitHub.
Appendix: source
Thrown at library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshot.java:63
@Override
public int getRetryingTimes() {
throw new NoFieldException("getRetryingTimes", this);
}
@Override
public boolean isResuming() {
throw new NoFieldException("isResuming", this);
}
@Override
public String getEtag() {
throw new NoFieldException("getEtag", this);
}
@Override
public long getLargeSofarBytes() {
throw new NoFieldException("getLargeSofarBytes", this);
}
@Override
public long getLargeTotalBytes() {
throw new NoFieldException("getLargeTotalBytes", this);
}
@Override
public int getSmallSofarBytes() {
throw new NoFieldException("getSmallSofarBytes", this);
}
@Override
public int getSmallTotalBytes() {
throw new NoFieldException("getSmallTotalBytes", this);
}
@OverrideView on GitHub (pinned to 6237a8cac1)