{"record":{"id":"30af4734de786fe1","repo":"Tencent/tinker","slug":"rest-bytes-insufficient-expect-to-read-bytes-b","errorCode":null,"errorMessage":"Rest bytes insufficient, expect to read {} bytes but only {} bytes were read.","messagePattern":"Rest bytes insufficient, expect to read (.+?) bytes but only (.+?) bytes were read\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"tinker-android/tinker-android-loader-no-op/src/main/java/com/tencent/tinker/loader/shareutil/ShareElfFile.java","lineNumber":116,"sourceCode":"            } else {\n                return FILE_TYPE_OTHERS;\n            }\n        } finally {\n            if (is != null) {\n                try {\n                    is.close();\n                } catch (Throwable thr) {\n                    // Ignored.\n                }\n            }\n        }\n    }\n\n    public static void readUntilLimit(FileChannel channel, ByteBuffer bufferOut, String errMsg) throws IOException {\n        bufferOut.rewind();\n        int bytesRead = channel.read(bufferOut);\n        if (bytesRead != bufferOut.limit()) {\n            throw new IOException(errMsg + \" Rest bytes insufficient, expect to read \"\n                    + bufferOut.limit() + \" bytes but only \"\n                    + bytesRead + \" bytes were read.\");\n        }\n        bufferOut.flip();\n    }\n\n    public static String readCString(ByteBuffer buffer) {\n        final byte[] rawBuffer = buffer.array();\n        int begin = buffer.position();\n        while (buffer.hasRemaining() && rawBuffer[buffer.position()] != 0) {\n            buffer.position(buffer.position() + 1);\n        }\n        // Move to the start of next cstring.\n        buffer.position(buffer.position() + 1);\n        return new String(rawBuffer, begin, buffer.position() - begin - 1, Charset.forName(\"ASCII\"));\n    }\n\n    public FileChannel getChannel() {","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-loader-no-op/src/main/java/com/tencent/tinker/loader/shareutil/ShareElfFile.java#L98-L134","documentation":"ShareElfFile.readUntilLimit reads exactly bufferOut.limit() bytes from a FileChannel; if the channel returns fewer bytes (including -1 for EOF) it throws IOException with the supplied message plus 'Rest bytes insufficient, expect to read X bytes but only Y bytes were read.'. Within Tinker this is used while parsing ELF files (.so libraries) and OAT/odex headers, so the throw means the file on disk is shorter than the ELF/OAT structure claims — a truncated file.","triggerScenarios":"Parsing a truncated .so from the patch lib directory or a truncated odex/oat file: the ELF header or section/program header extends past the actual file size. Also triggered when a non-ELF path points at a short file after the magic check passed by luck.","commonSituations":"Partially downloaded/applied patch leaving truncated .so files; disk-full during patch apply; odex file cut off after an interrupted dexopt; storage corruption on aging devices.","solutions":["cleanPatch() and re-apply the patch so all native libs restore intact.","Validate patch file md5 before applying so corrupt downloads never install.","Ensure sufficient free storage before patch apply.","If parsing your own ELF files with ShareElfFile, verify file length against the header's e_shoff+e_shnum*e_shentsize before reading."],"exampleFix":"// before\nShareElfFile elf = new ShareElfFile(soFile); // may throw mid-parse\n\n// after: pre-check size plausibility\nif (soFile.length() < ElfHeader.MIN_ELF_SIZE) {\n    throw new IOException(\"truncated so file: \" + soFile);\n}","handlingStrategy":"validation","validationCode":"if (file.length() < 52 /* minimum 64-bit ehdr */) {\n    throw new IOException(\"file too small to be ELF: \" + file);\n}","typeGuard":null,"tryCatchPattern":"try {\n    elfFile = new ShareElfFile(soFile);\n} catch (IOException e) {\n    // truncated or corrupt binary: reject and re-download/cleanPatch\n}","preventionTips":["Check free disk space before patch apply","Verify md5 of downloaded patch files","Treat short reads during ELF parsing as corruption, not retryable I/O"],"tags":["tinker","android","elf","truncated-file","io"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}