lionsoul2014/ip2region · error · IOException
incomplete read: read bytes should be ${buffer.length}
Error message
incomplete read: read bytes should be ${buffer.length} What it means
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.
Source
Thrown at binding/java/src/main/java/org/lionsoul/ip2region/xdb/Searcher.java:196
read(dataPtr, regionBuff);
return new String(regionBuff, "utf-8");
}
protected void read(long offset, byte[] buffer) throws IOException {
// check the in-memory buffer first
if (contentBuff != null) {
contentBuff.copy(offset, buffer, 0, buffer.length);
return;
}
// read from the file handle
assert handle != null;
handle.seek(offset);
this.ioCount++;
int rLen = handle.read(buffer);
if (rLen != buffer.length) {
throw new IOException("incomplete read: read bytes should be " + buffer.length);
}
}
@Override public String toString() {
return String.format(
"%s->{version:%s, xdb:%s, vIndex:%s, cBuffer:%s}",
super.toString(),
version.name, xdbFile == null ? "null" : xdbFile.getAbsolutePath(),
vectorIndex == null ? "null" : String.valueOf(vectorIndex.length),
contentBuff == null ? "null" : String.valueOf(contentBuff.length())
);
}
// ---
// --- static util function
// --- read xdb header
public static Header loadHeader(RandomAccessFile handle) throws IOException {View on GitHub (pinned to c1a1fc7d59)
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
Example fix
// before
raf = new RandomAccessFile("/data/ip2region.xdb", "r"); // truncated copy
// after
if (new File("/data/ip2region.xdb").length() < expectedSize) throw ...;
raf = new RandomAccessFile("/data/ip2region.xdb.tmp.ready", "r"); Defensive patterns
Strategy: try-catch
Validate before calling
File f = new File(xdbPath);
if (!f.isFile() || f.length() < 256) throw new IllegalStateException("xdb missing/truncated: " + xdbPath);
try (RandomAccessFile raf = new RandomAccessFile(f, "r")) { Searcher.verify(raf); } Try / catch
try {
return searcher.search(ip);
} catch (IOException e) {
log.error("xdb read failed, reloading searcher", e);
reloadSearcher(); // reopen after integrity check
return null;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Deploying a partial xdb file; replacing the xdb while searchers still hold open handles; NFS/S3-mounted files with flaky IO.
Related errors
- incomplete read: read bytes should be ${len}
- incomplete read: read bytes should be ${buff.length}, got `$
- ip verison not match: xdb file ${xdbFile.getAbsolutePath()}
- invalid cache policy `${name}`
- SetXdbInputStream could ONLY be used with cachePolicy = Conf
AI-assisted analysis of lionsoul2014/ip2region@c1a1fc7d59 (2026-09-02).
Data as JSON: /api/errors/2e5025f113b93619.
Report an issue: GitHub.