{"record":{"id":"726788ca5b689c71","repo":"lingochamp/FileDownloader","slug":"getlargetotalbytes","errorCode":null,"errorMessage":"getLargeTotalBytes","messagePattern":"getLargeTotalBytes","errorType":"exception","errorClass":"NoFieldException","httpStatus":null,"severity":"error","filePath":"library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshot.java","lineNumber":68,"sourceCode":"\n    @Override\n    public boolean isResuming() {\n        throw new NoFieldException(\"isResuming\", this);\n    }\n\n    @Override\n    public String getEtag() {\n        throw new NoFieldException(\"getEtag\", this);\n    }\n\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","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/lingochamp/FileDownloader/blob/6237a8cac174bcc916e4342b14ab1ab72a5768d4/library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshot.java#L50-L86","documentation":"getLargeTotalBytes() is one of the accessors MessageSnapshot's base class deliberately implements by throwing NoFieldException. Only snapshots that carry the large-file total size (progress/connected/error/completed large snapshots) override it. Throwing means the snapshot's status has no 'total bytes' field, so the caller queried a field that does not exist for this message.","triggerScenarios":"Calling getLargeTotalBytes() on a snapshot whose status is started, warn, pending (small variant), retry, or similar; internally this is reached from the update() and handoverMessage() paths that translate a status-change snapshot without dispatching on its type.","commonSituations":"Progress UI code reading total bytes in a 'started' or 'warn' callback; code assuming every snapshot has total/sofar fields; Parcelable deserialization producing a snapshot class that does not hold the field and then being inspected; library versions where the accessor was moved from a concrete class to a throwing base default.","solutions":["Guard with getStatus()/isLargeFile() before calling getLargeTotalBytes(); read it only for progress or connected snapshots of a large file.","Fix the internal update/handoverMessage conversion to select the correct accessor for the concrete snapshot class.","Cache the total bytes returned during the progress callback and reuse the cached value for other statuses.","Verify the snapshot was built through MessageSnapshot.CREATOR so the status-appropriate subclass is instantiated."],"exampleFix":"// before\nlong total = snapshot.getLargeTotalBytes(); // throws for warn/started snapshots\n\n// after\nlong total = 0;\nif (snapshot.getStatus() == FileDownloadStatus.progress\n        || snapshot.getStatus() == FileDownloadStatus.connected) {\n    total = snapshot.getLargeTotalBytes();\n}","handlingStrategy":"type-guard","validationCode":"public static boolean hasLargeTotal(IMessageSnapshot s) {\n    return s.isLargeFile()\n        && (s.getStatus() == FileDownloadStatus.progress\n            || s.getStatus() == FileDownloadStatus.connected);\n}","typeGuard":"public static boolean exposesTotalBytes(IMessageSnapshot s) {\n    byte st = s.getStatus();\n    return st == FileDownloadStatus.progress\n        || st == FileDownloadStatus.connected;\n}\n// usage: long total = exposesTotalBytes(snap) ? snap.getLargeTotalBytes() : cachedTotal;","tryCatchPattern":"long total;\ntry {\n    total = snapshot.getLargeTotalBytes();\n} catch (IllegalStateException e) {\n    total = cachedTotalBytes; // value remembered from progress callback\n}","preventionTips":["Read total bytes only in the progress/connected stages of the listener.","Persist the total once obtained and reuse it for other statuses.","Do not call every accessor on a snapshot generically; treat fields as status-specific.","When deserializing via MessageSnapshot.CREATOR, rely on the status-appropriate subclass rather than casting."],"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"}