lingochamp/FileDownloader · error · NoFieldException

getSmallSofarBytes

Error message

getSmallSofarBytes

What it means

getSmallSofarBytes() is another base-class accessor in MessageSnapshot that throws NoFieldException unless overridden by a snapshot carrying small-file progress (e.g. SmallMessageSnapshot.ProgressMessageSnapshot). The throw indicates the sofar-bytes field does not exist for this snapshot's status, so the query is a programming error by the consumer.

Solutions

  1. Dispatch on snapshot.isLargeFile(): use getSmallSofarBytes() only for small-file snapshots, getLargeSofarBytes() for large ones.
  2. Check getStatus() is progress/connected before reading any sofar-bytes accessor.
  3. Fix the internal handoverMessage() logic to only query fields present on the concrete snapshot class.
  4. Fall back to getSmallSofarBytes()/getLargeSofarBytes() inside a try-catch for IllegalStateException if snapshot provenance cannot be determined.

Example fix

// before
int sofar = snapshot.getSmallSofarBytes();

// after
int sofar = snapshot.isLargeFile()
    ? (int) snapshot.getLargeSofarBytes()
    : snapshot.getSmallSofarBytes();
Defensive patterns

Strategy: type-guard

Validate before calling

public static boolean hasSmallProgress(IMessageSnapshot s) {
    return !s.isLargeFile()
        && (s.getStatus() == FileDownloadStatus.progress
            || s.getStatus() == FileDownloadStatus.connected);
}

Type guard

public static boolean canReadSmallSofar(IMessageSnapshot s) {
    return !s.isLargeFile()
        && (s.getStatus() == FileDownloadStatus.progress
            || s.getStatus() == FileDownloadStatus.connected);
}
// usage: int sofar = canReadSmallSofar(snap) ? snap.getSmallSofarBytes() : 0;

Try / catch

int sofar;
try {
    sofar = snapshot.getSmallSofarBytes();
} catch (IllegalStateException e) {
    sofar = snapshot.isLargeFile()
        ? (int) lastKnownLargeSofar
        : lastKnownSmallSofar;
}

Prevention

When it happens

Trigger: Calling getSmallSofarBytes() on a large-file snapshot (which exposes getLargeSofarBytes instead) or on status snapshots without progress data (started, warn, completed, error, pending-large); internally reached from handoverMessage() when a status-change snapshot is inspected for progress fields.

Common situations: Code that reads small-file fields without checking isLargeFile(); shared listener code written for small downloads then applied to large downloads (maxBytesOverMobile / file-size thresholds); snapshots moved across process boundaries and re-inspected for fields they never carried.

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/1ba76512fec7a8ae. Report an issue: GitHub.

Appendix: source

Thrown at library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshot.java:73

    @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);
    }

    @Override
    public boolean isReusedDownloadedFile() {
        throw new NoFieldException("isReusedDownloadedFile", this);
    }

    @Override
    public String getFileName() {
        throw new NoFieldException("getFileName", this);
    }

    @Override

View on GitHub (pinned to 6237a8cac1)