{"record":{"id":"95cde9f3d0691a53","repo":"lingochamp/FileDownloader","slug":"isreuseddownloadedfile","errorCode":null,"errorMessage":"isReusedDownloadedFile","messagePattern":"isReusedDownloadedFile","errorType":"exception","errorClass":"NoFieldException","httpStatus":null,"severity":"error","filePath":"library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshot.java","lineNumber":83,"sourceCode":"\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\n    public interface IWarnMessageSnapshot {\n        MessageSnapshot turnToPending();\n    }\n\n","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/lingochamp/FileDownloader/blob/6237a8cac174bcc916e4342b14ab1ab72a5768d4/library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshot.java#L65-L101","documentation":"isReusedDownloadedFile() is a base-class accessor in MessageSnapshot that throws NoFieldException because most snapshots (started, pending, progress, etc.) do not record whether the downloaded file was reused; only the completed/warn snapshots carry that flag. Throwing means the flag does not exist for this snapshot's status and the caller asked for data the message never had.","triggerScenarios":"Calling isReusedDownloadedFile() on a snapshot with a status other than completed (or the statuses whose concrete class overrides it); internally invoked from the update() path that re-inspects every snapshot with the full accessor set.","commonSituations":"Listener code checking reuse status in every callback instead of only in blockComplete/completed; logic that decides whether to skip re-downloading based on a snapshot of the wrong status; library upgrades that turned previously-null-returning accessors into throwing ones, exposing latent unconditional calls.","solutions":["Call isReusedDownloadedFile() only when getStatus() == FileDownloadStatus.completed (or on snapshots whose class overrides it).","Fix the internal update() conversion to avoid querying the reuse flag on snapshots that do not carry it.","Track reuse yourself: record it when the completed callback delivers a snapshot where the call succeeds, and use the recorded value elsewhere.","Wrap the call in a try-catch for IllegalStateException as a last resort when snapshot type cannot be determined statically."],"exampleFix":"// before\nboolean reused = snapshot.isReusedDownloadedFile(); // throws for progress snapshots\n\n// after\nboolean reused = snapshot.getStatus() == FileDownloadStatus.completed\n    && snapshot.isReusedDownloadedFile();","handlingStrategy":"type-guard","validationCode":"public static boolean hasReusedFlag(IMessageSnapshot s) {\n    return s.getStatus() == FileDownloadStatus.completed;\n}","typeGuard":"public static Boolean reusedDownloadedFileIfPresent(IMessageSnapshot s) {\n    if (s.getStatus() != FileDownloadStatus.completed) return null;\n    try {\n        return s.isReusedDownloadedFile();\n    } catch (IllegalStateException e) {\n        return null; // snapshot class does not carry the flag\n    }\n}","tryCatchPattern":"boolean reused = false;\ntry {\n    reused = snapshot.isReusedDownloadedFile();\n} catch (IllegalStateException e) {\n    // flag not present for this status; treat as not reused\n    reused = false;\n}","preventionTips":["Only inspect the reused-file flag in the completed callback.","Remember the flag when it is available and use the remembered value in other code paths.","Treat IMessageSnapshot accessors as status-scoped, not uniformly available.","After library upgrades, re-test any code calling accessor methods that may now throw by default."],"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"}