{"record":{"id":"8f9eb2bb409bf26f","repo":"microg/GmsCore","slug":"could-not-read-from-parcel-file-descriptor","errorCode":null,"errorMessage":"Could not read from parcel file descriptor","messagePattern":"Could not read from parcel file descriptor","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"play-services-base/src/main/java/com/google/android/gms/common/data/BitmapTeleporter.java","lineNumber":78,"sourceCode":"            if (parcelFileDescriptor == null) {\n                throw new NullPointerException(\"null reference\");\n            }\n            DataInputStream dataInputStream = new DataInputStream(new ParcelFileDescriptor.AutoCloseInputStream(parcelFileDescriptor));\n            try {\n                try {\n                    byte[] bArr = new byte[dataInputStream.readInt()];\n                    int readInt = dataInputStream.readInt();\n                    int readInt2 = dataInputStream.readInt();\n                    Bitmap.Config valueOf = Bitmap.Config.valueOf(dataInputStream.readUTF());\n                    dataInputStream.read(bArr);\n                    close(dataInputStream);\n                    ByteBuffer wrap = ByteBuffer.wrap(bArr);\n                    Bitmap createBitmap = Bitmap.createBitmap(readInt, readInt2, valueOf);\n                    createBitmap.copyPixelsFromBuffer(wrap);\n                    this.targetBitmap = createBitmap;\n                    this.isParceled = true;\n                } catch (IOException e) {\n                    throw new IllegalStateException(\"Could not read from parcel file descriptor\", e);\n                }\n            } catch (Throwable th) {\n                close(dataInputStream);\n                throw th;\n            }\n        }\n        return this.targetBitmap;\n    }\n\n    public final void setTargetDirectory(File file) {\n        if (file == null) {\n            throw new NullPointerException(\"Cannot set null temp directory\");\n        }\n        this.targetDirectory = file;\n    }\n\n    private static void close(Closeable closeable) {\n        try {","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-base/src/main/java/com/google/android/gms/common/data/BitmapTeleporter.java#L60-L96","documentation":"createTargetBitmap wraps any IOException raised while reading the bitmap bytes from the ParcelFileDescriptor in an IllegalStateException('Could not read from parcel file descriptor', e). This means the descriptor exists but the underlying pipe/temp file could not be read to completion (length fields or pixel data failed).","triggerScenarios":"The AutoCloseInputStream hits EOF early because the producer closed the pipe or the process died; the temp file backing the descriptor was deleted before reading; corrupted/short data written during parceling; I/O errors on storage holding the temp directory.","commonSituations":"Passing a BitmapTeleporter across processes and reading it after the sender finished/crashed; a full or cleaned temp directory (targetDirectory) removed between write and read; large bitmaps truncated by dead binder transactions.","solutions":["Read/createTargetBitmap in the same process lifetime and before any cleanup of the temp directory used at parcel time.","Set a valid, writable temp directory via setTargetDirectory(new File(context.getCacheDir(), \"bitmaps\")) so the temp file persists for the read.","Inspect the cause exception to distinguish premature EOF vs filesystem errors; if premature EOF, re-transmit the bitmap.","Retry the whole parcel/transfer round-trip; the current payload is unrecoverable."],"exampleFix":"// before\nBitmap bmp = teleporter.createTargetBitmap(); // IllegalStateException on I/O failure\n\n// after\ntry {\n    Bitmap bmp = teleporter.createTargetBitmap();\n} catch (IllegalStateException e) {\n    Log.w(TAG, \"Bitmap transfer failed, re-sending\", e.getCause());\n    resendBitmap(originalBitmap);\n}","handlingStrategy":"try-catch","validationCode":"ParcelFileDescriptor fd = getDescriptorIfPresent(teleporter);\nif (fd == null || !fd.getFileDescriptor().valid()) {\n    Log.w(TAG, \"Descriptor invalid; re-transfer needed\");\n}","typeGuard":"boolean canReadDescriptor(ParcelFileDescriptor fd) {\n    return fd != null && fd.getFileDescriptor() != null && fd.getFileDescriptor().valid();\n}","tryCatchPattern":"try {\n    return teleporter.createTargetBitmap();\n} catch (IllegalStateException e) {\n    Log.w(TAG, \"Failed to read bitmap from descriptor\", e.getCause());\n    retryTransferOnce();\n    return null;\n}","preventionTips":["Read the bitmap before the sender process finishes/cleans temp files.","Point setTargetDirectory at app-internal cache (cacheDir), not external storage that can be unmounted.","Keep the full parcel->read round-trip inside one failure-handling boundary so it can be retried.","Log e.getCause() (the IOException) to distinguish EOF-truncation from filesystem errors."],"tags":["android","io","parcel","bitmap"],"backgroundTag":"file-read-failed","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}