{"record":{"id":"af48acd92f7a02ed","repo":"lingochamp/FileDownloader","slug":"getsmalltotalbytes","errorCode":null,"errorMessage":"getSmallTotalBytes","messagePattern":"getSmallTotalBytes","errorType":"exception","errorClass":"NoFieldException","httpStatus":null,"severity":"error","filePath":"library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshot.java","lineNumber":78,"sourceCode":"\n    @Override\n    public long getLargeSofarBytes() {\n        throw new NoFieldException(\"getLargeSofarBytes\", this);\n    }\n\n    @Override\n    public long getLargeTotalBytes() {\n        throw new NoFieldException(\"getLargeTotalBytes\", this);\n    }\n\n    @Override\n    public int getSmallSofarBytes() {\n        throw new NoFieldException(\"getSmallSofarBytes\", this);\n    }\n\n    @Override\n    public int getSmallTotalBytes() {\n        throw new NoFieldException(\"getSmallTotalBytes\", this);\n    }\n\n    @Override\n    public boolean isReusedDownloadedFile() {\n        throw new NoFieldException(\"isReusedDownloadedFile\", this);\n    }\n\n    @Override\n    public String getFileName() {\n        throw new NoFieldException(\"getFileName\", this);\n    }\n\n    @Override\n    public boolean isLargeFile() {\n        return isLargeFile;\n    }\n\n","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/lingochamp/FileDownloader/blob/6237a8cac174bcc916e4342b14ab1ab72a5768d4/library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshot.java#L60-L96","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nint total = snapshot.getSmallTotalBytes();\n\n// after\nint total = snapshot.isLargeFile()\n    ? (int) snapshot.getLargeTotalBytes()\n    : snapshot.getSmallTotalBytes();","handlingStrategy":"type-guard","validationCode":"public static boolean hasSmallTotal(IMessageSnapshot s) {\n    return !s.isLargeFile()\n        && (s.getStatus() == FileDownloadStatus.progress\n            || s.getStatus() == FileDownloadStatus.connected);\n}","typeGuard":"public static boolean canReadSmallTotal(IMessageSnapshot s) {\n    return !s.isLargeFile()\n        && (s.getStatus() == FileDownloadStatus.progress\n            || s.getStatus() == FileDownloadStatus.connected);\n}\n// usage: int total = canReadSmallTotal(snap) ? snap.getSmallTotalBytes() : cachedTotal;","tryCatchPattern":"int total;\ntry {\n    total = snapshot.getSmallTotalBytes();\n} catch (IllegalStateException e) {\n    total = cachedSmallTotal; // remembered from the last progress event\n}","preventionTips":["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."],"tags":["android","filedownloader","message-snapshot","illegal-state"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6237a8cac174bcc916e4342b14ab1ab72a5768d4","analyzedAt":"2026-09-08T23:50:48.168Z","contentChangedAt":"2026-09-08T23:50:48.168Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}