koral--/android-gif-drawable · error · GifIOException
GifError.OPEN_FAILED.errorCode
GifError.OPEN_FAILED.errorCode
Error message
<e.getMessage()>
What it means
openFileDescriptor wraps any exception raised while obtaining the native file descriptor into a GifIOException with GifError.OPEN_FAILED.errorCode and the underlying exception's message. It catches generic Exception because catching ErrnoException directly causes VerifyError on API <= 19. The thrown GifIOException therefore signals the OS-level open of the descriptor failed.
Solutions
- Inspect e.getMessage()/cause in the GifIOException and ensure the FileDescriptor is valid and open before constructing the drawable.
- Keep the ParcelFileDescriptor open while the GIF is in use; do not close it prematurely.
- Check file permissions and that the underlying file still exists.
- On older APIs verify the fallback extractNativeFileDescriptor path is being reached correctly.
Example fix
// before pfd.close(); GifDrawable d = new GifDrawableBuilder().from(pfd.getFileDescriptor()).build(); // after GifDrawable d = new GifDrawableBuilder().from(pfd.getFileDescriptor()).build(); // close pfd only after the drawable is no longer needed
Defensive patterns
Strategy: try-catch
Validate before calling
if (fileDescriptor != null && fileDescriptor.valid()) { /* proceed */ } Try / catch
try { d = new GifDrawableBuilder().from(fd).build(); } catch (GifIOException e) { if (e.getErrorCode() == GifError.OPEN_FAILED.errorCode) { /* fd open failed: re-open source or notify user */ } } Prevention
- Keep ParcelFileDescriptors open while the drawable lives
- Validate descriptors before use
- Check file permissions on the underlying resource
When it happens
Trigger: Passing an invalid/closed FileDescriptor, or a descriptor whose dup/extract fails (e.g. ErrnoException EBADF) via ParcelFileDescriptor on Android > O_MR1 to a GifDrawable built from a FileDescriptor source.
Common situations: Using a ParcelFileDescriptor after closing it; file permissions revoked; passing descriptors obtained from a ContentProvider that has since been released.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- InputStream does not support marking
- Could not open AssetFileDescriptor for
- Sample size out of range <1, 65535>
- Bitmap is recycled
- Bitmap ia too small, size must be greater than or equal to…
AI-assisted analysis of koral--/android-gif-drawable@26ff795f78 (2026-09-10).
Data as JSON: /api/errors/59a89f00b576fcfe.
Report an issue: GitHub.
Appendix: source
Thrown at android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifInfoHandle.java:78
GifInfoHandle(AssetFileDescriptor afd) throws IOException {
try {
gifInfoPtr = openFileDescriptor(afd.getFileDescriptor(), afd.getStartOffset(), false);
} finally {
try {
afd.close();
} catch (IOException ignored) {
//no-op
}
}
}
private static long openFileDescriptor(FileDescriptor fileDescriptor, long offset, boolean closeOriginalDescriptor) throws GifIOException {
final int nativeFileDescriptor;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O_MR1) {
try {
nativeFileDescriptor = getNativeFileDescriptor(fileDescriptor, closeOriginalDescriptor);
} catch (Exception e) { //cannot catch ErrnoException due to VerifyError on API <= 19
throw new GifIOException(GifError.OPEN_FAILED.errorCode, e.getMessage());
}
} else {
nativeFileDescriptor = extractNativeFileDescriptor(fileDescriptor, closeOriginalDescriptor);
}
return openNativeFileDescriptor(nativeFileDescriptor, offset);
}
private static int getNativeFileDescriptor(FileDescriptor fileDescriptor, boolean closeOriginalDescriptor) throws GifIOException, ErrnoException {
try {
final int nativeFileDescriptor = createTempNativeFileDescriptor();
Os.dup2(fileDescriptor, nativeFileDescriptor);
return nativeFileDescriptor;
} finally {
if (closeOriginalDescriptor) {
Os.close(fileDescriptor);
}
}
}View on GitHub (pinned to 26ff795f78)