{"record":{"id":"2e5025f113b93619","repo":"lionsoul2014/ip2region","slug":"incomplete-read-read-bytes-should-be-buffer-len","errorCode":null,"errorMessage":"incomplete read: read bytes should be ${buffer.length}","messagePattern":"incomplete read: read bytes should be (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"binding/java/src/main/java/org/lionsoul/ip2region/xdb/Searcher.java","lineNumber":196,"sourceCode":"        read(dataPtr, regionBuff);\n        return new String(regionBuff, \"utf-8\");\n    }\n\n    protected void read(long offset, byte[] buffer) throws IOException {\n        // check the in-memory buffer first\n        if (contentBuff != null) {\n            contentBuff.copy(offset, buffer, 0, buffer.length);\n            return;\n        }\n\n        // read from the file handle\n        assert handle != null;\n        handle.seek(offset);\n\n        this.ioCount++;\n        int rLen = handle.read(buffer);\n        if (rLen != buffer.length) {\n            throw new IOException(\"incomplete read: read bytes should be \" + buffer.length);\n        }\n    }\n\n    @Override public String toString() {\n        return String.format(\n            \"%s->{version:%s, xdb:%s, vIndex:%s, cBuffer:%s}\", \n            super.toString(),\n            version.name, xdbFile == null ? \"null\" : xdbFile.getAbsolutePath(), \n            vectorIndex == null ? \"null\" : String.valueOf(vectorIndex.length),\n            contentBuff == null ? \"null\" : String.valueOf(contentBuff.length())\n        );\n    }\n\n    // ---\n    // --- static util function\n    // --- read xdb header\n\n    public static Header loadHeader(RandomAccessFile handle) throws IOException {","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/lionsoul2014/ip2region/blob/c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1/binding/java/src/main/java/org/lionsoul/ip2region/xdb/Searcher.java#L178-L214","documentation":"The file-based read() helper seeks to an offset and reads exactly buffer.length bytes; RandomAccessFile.read may return fewer bytes than requested, and this code treats any short read as a corrupted/truncated xdb and throws IOException. It guards against silently using incomplete data.","triggerScenarios":"Reading the xdb via RandomAccessFile when the file is truncated, being rewritten concurrently, sits on a failing/mounted-later network share, or the offset points past meaningful data.","commonSituations":"Deploying a partial xdb file; replacing the xdb while searchers still hold open handles; NFS/S3-mounted files with flaky IO.","solutions":["Verify the xdb file integrity (re-download/re-copy it; Searcher.verify can check the header)","Ensure the xdb file is fully written before searchers open it (atomic rename after copy)","Stop sharing the file between writers and readers; open a new searcher after each xdb update","Retry on transient IO errors if the storage layer is unreliable"],"exampleFix":"// before\nraf = new RandomAccessFile(\"/data/ip2region.xdb\", \"r\"); // truncated copy\n// after\nif (new File(\"/data/ip2region.xdb\").length() < expectedSize) throw ...;\nraf = new RandomAccessFile(\"/data/ip2region.xdb.tmp.ready\", \"r\");","handlingStrategy":"try-catch","validationCode":"File f = new File(xdbPath);\nif (!f.isFile() || f.length() < 256) throw new IllegalStateException(\"xdb missing/truncated: \" + xdbPath);\ntry (RandomAccessFile raf = new RandomAccessFile(f, \"r\")) { Searcher.verify(raf); }","typeGuard":null,"tryCatchPattern":"try {\n    return searcher.search(ip);\n} catch (IOException e) {\n    log.error(\"xdb read failed, reloading searcher\", e);\n    reloadSearcher(); // reopen after integrity check\n    return null;\n}","preventionTips":["Publish xdb updates atomically (write temp file then rename)","Verify file integrity with Searcher.verify at startup","Avoid holding long-lived handles across xdb deployments","Store xdb on local disk, not flaky network mounts"],"tags":["java","io","corrupt-file"],"backgroundTag":"incomplete-read","analyzedSha":"c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1","analyzedAt":"2026-09-02T16:58:39.988Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}