{"record":{"id":"3b19f0eb0f727331","repo":"lingochamp/FileDownloader","slug":"getetag","errorCode":null,"errorMessage":"getEtag","messagePattern":"getEtag","errorType":"exception","errorClass":"NoFieldException","httpStatus":null,"severity":"error","filePath":"library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshot.java","lineNumber":58,"sourceCode":"\n    @Override\n    public Throwable getThrowable() {\n        throw new NoFieldException(\"getThrowable\", this);\n    }\n\n    @Override\n    public int getRetryingTimes() {\n        throw new NoFieldException(\"getRetryingTimes\", this);\n    }\n\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","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/lingochamp/FileDownloader/blob/6237a8cac174bcc916e4342b14ab1ab72a5768d4/library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshot.java#L40-L76","documentation":"MessageSnapshot's base getEtag() throws NoFieldException because this snapshot type carries no ETag field. Only connected-status snapshots (which hold the HTTP ETag from the server response) override getEtag(); calling it on any other snapshot type is invalid.","triggerScenarios":"Calling IMessageSnapshot.getEtag() on a MessageSnapshot whose class is not a ConnectedMessageSnapshot — e.g. pending, progress, or error snapshots. Triggered through update/handoverMessage message inspection or direct snapshot probing.","commonSituations":"Breakpoint-resume logic that wants the server ETag from every lifecycle message; code caching ETags without filtering for the connected status; version mismatches where the callback contract changed.","solutions":["Call getEtag() only when getStatus() == FileDownloadStatus.connected","Retrieve the ETag from the HTTP layer or task data you control instead of the snapshot","Catch IllegalStateException around the accessor when processing snapshots generically","If ETag persistence matters, record it in your own storage at the connected callback point"],"exampleFix":"// before\nString etag = snapshot.getEtag();\n// after\nString etag = snapshot.getStatus() == FileDownloadStatus.connected ? snapshot.getEtag() : null;","handlingStrategy":"validation","validationCode":"if (snapshot.getStatus() != FileDownloadStatus.connected) {\n    return null; // no ETag field on this snapshot\n}","typeGuard":"String safeGetEtag(IMessageSnapshot s) {\n    if (s.getStatus() != FileDownloadStatus.connected) return null;\n    try { return s.getEtag(); } catch (IllegalStateException e) { return null; }\n}","tryCatchPattern":"try {\n    String etag = snapshot.getEtag();\n} catch (IllegalStateException e) {\n    // snapshot has no etag field for this status\n}","preventionTips":["Call getEtag() only on connected-status snapshots","Persist the ETag yourself at the connected callback instead of probing later messages","Guard snapshot accessors by status checks","Catch IllegalStateException in any generic snapshot iteration code"],"tags":["android","filedownloader","no-field","snapshot-accessor"],"backgroundTag":"unsupported-operation","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"}