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

  1. Inspect e.getMessage()/cause in the GifIOException and ensure the FileDescriptor is valid and open before constructing the drawable.
  2. Keep the ParcelFileDescriptor open while the GIF is in use; do not close it prematurely.
  3. Check file permissions and that the underlying file still exists.
  4. 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

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


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)