lingochamp/FileDownloader · error · NoFieldException
getSmallTotalBytes
Error message
getSmallTotalBytes
What it means
getSmallTotalBytes() follows the same pattern as the other MessageSnapshot accessors: the base class throws NoFieldException, and only small-file snapshots that actually store the total size override it. The exception states that this snapshot's status/type has no small-total-bytes field, so reading it is an invalid access on that message.
Solutions
- Only call getSmallTotalBytes() when snapshot.isLargeFile() is false and getStatus() is progress or connected.
- Use the accessor pair matching the file type (small vs large) consistently in the listener.
- Correct the internal handoverMessage()/update() conversion code to type-dispatch on the snapshot class.
- Keep the last known total from the progress callback and reuse it for other statuses instead of querying snapshots that lack the field.
Example fix
// before
int total = snapshot.getSmallTotalBytes();
// after
int total = snapshot.isLargeFile()
? (int) snapshot.getLargeTotalBytes()
: snapshot.getSmallTotalBytes(); Defensive patterns
Strategy: type-guard
Validate before calling
public static boolean hasSmallTotal(IMessageSnapshot s) {
return !s.isLargeFile()
&& (s.getStatus() == FileDownloadStatus.progress
|| s.getStatus() == FileDownloadStatus.connected);
} Type guard
public static boolean canReadSmallTotal(IMessageSnapshot s) {
return !s.isLargeFile()
&& (s.getStatus() == FileDownloadStatus.progress
|| s.getStatus() == FileDownloadStatus.connected);
}
// usage: int total = canReadSmallTotal(snap) ? snap.getSmallTotalBytes() : cachedTotal; Try / catch
int total;
try {
total = snapshot.getSmallTotalBytes();
} catch (IllegalStateException e) {
total = cachedSmallTotal; // remembered from the last progress event
} Prevention
- Match the accessor pair (getSmallSofarBytes/getSmallTotalBytes vs large) to isLargeFile().
- Compute percentages only inside the progress callback where both fields exist.
- Do not query totals on completed/error snapshots; use the values captured earlier.
- Keep listener handling per-status instead of a single generic block.
When it happens
Trigger: Calling getSmallTotalBytes() on a large-file snapshot, or on a status without byte fields (started, warn, completed, error, retry); internally triggered from handoverMessage() when it inspects a non-progress snapshot for small-file totals.
Common situations: Progress calculations (sofar/total percentage) executed in every listener callback regardless of status; code mixing up small and large accessor pairs after a download switched to large-file mode; serialized snapshots restored in another process and queried generically.
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
- getLargeSofarBytes
- getLargeTotalBytes
- getSmallSofarBytes
- isReusedDownloadedFile
- fetched length[ ] != content length[ ], range[ , ) offset[…
AI-assisted analysis of lingochamp/FileDownloader@6237a8cac1 (2026-09-08).
Data as JSON: /api/errors/af48acd92f7a02ed.
Report an issue: GitHub.
Appendix: source
Thrown at library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshot.java:78
@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);
}
@Override
public boolean isReusedDownloadedFile() {
throw new NoFieldException("isReusedDownloadedFile", this);
}
@Override
public String getFileName() {
throw new NoFieldException("getFileName", this);
}
@Override
public boolean isLargeFile() {
return isLargeFile;
}
View on GitHub (pinned to 6237a8cac1)