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

  1. Only call getSmallTotalBytes() when snapshot.isLargeFile() is false and getStatus() is progress or connected.
  2. Use the accessor pair matching the file type (small vs large) consistently in the listener.
  3. Correct the internal handoverMessage()/update() conversion code to type-dispatch on the snapshot class.
  4. 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

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


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)