lionsoul2014/ip2region · critical · Error

incomplete read (${rBytes} read, ${vBytes} expected)

Error message

incomplete read (${rBytes} read, ${vBytes} expected)

What it means

loadVectorIndex reads the vector index region (VectorIndexCols * VectorIndexRows * VectorIndexSize bytes) starting at HeaderInfoLength. A short read means the file ends before the vector index completes, so region lookups would return garbage; the library throws with read vs expected byte counts.

Source

Thrown at binding/javascript/util.js:359

    if (rBytes != HeaderInfoLength) {
        throw new Error(`incomplete read (${rBytes} read, ${header.HeaderInfoLength} expected)`);
    }
    return new Header(buffer);
}

export function loadHeaderFromFile(dbPath) {
    const fd = fs.openSync(dbPath, "r");
    const header = loadHeader(fd);
    fs.closeSync(fd);
    return header;
}

export function loadVectorIndex(fd) {
    const vBytes = VectorIndexCols * VectorIndexRows * VectorIndexSize;
    const buffer = Buffer.alloc(vBytes);
    const rBytes = fs.readSync(fd, buffer, 0, vBytes, HeaderInfoLength);
    if (rBytes != vBytes) {
        throw new Error(`incomplete read (${rBytes} read, ${vBytes} expected)`);
    }
    return buffer;
}

export function loadVectorIndexFromFile(dbPath) {
    const fd = fs.openSync(dbPath, "r");
    const vIndex = loadVectorIndex(fd);
    fs.closeSync(fd);
    return vIndex;
}

export function loadContent(fd) {
    const stats = fs.fstatSync(fd);
    const buffer = Buffer.alloc(stats.size);
    const rBytes = fs.readSync(fd, buffer, 0, buffer.length, 0);
    if (rBytes != stats.size) {
        throw new Error(`incomplete read (${rBytes} read, ${stats.size} expected)`);
    }

View on GitHub (pinned to c1a1fc7d59)

Solutions

  1. Replace the data file with a verified full copy of the official xdb file (check size and hash).
  2. Do not edit/trim the xdb file; the header, vector index and content must stay contiguous.
  3. Ensure the file is not being read while a writer (maker) is still producing it.
  4. Pre-check fs.fstatSync(fd).size >= HeaderInfoLength + vBytes before loading.

Example fix

// before
const vIndex = loadVectorIndex(fd); // throws if truncated
// after
const need = HeaderInfoLength + VectorIndexCols * VectorIndexRows * VectorIndexSize;
if (fs.fstatSync(fd).size < need) throw new Error('xdb too small for vector index');
const vIndex = loadVectorIndex(fd);
Defensive patterns

Strategy: validation

Validate before calling

const need = HeaderInfoLength + VectorIndexCols * VectorIndexRows * VectorIndexSize;
if (fs.fstatSync(fd).size < need)
  throw new Error('xdb too small: vector index region missing');

Try / catch

try {
  const vIndex = loadVectorIndex(fd);
} catch (e) {
  if (String(e.message).includes('incomplete read')) {
    // reload from a verified copy of the db file
    throw new Error('xdb vector index truncated; restore full file');
  }
  throw e;
}

Prevention

When it happens

Trigger: loadVectorIndex(fd) / vIndex() on a truncated xdb: file smaller than HeaderInfoLength + vBytes, partial download, wrong file, or a hand-trimmed database.

Common situations: Failed or resumable-download artifact; copying the file while the updater writes it; slicing an xdb to ship 'only what's needed' and cutting off the index region.

Related errors


AI-assisted analysis of lionsoul2014/ip2region@c1a1fc7d59 (2026-09-02). Data as JSON: /api/errors/15e9b1ab0a7a4526. Report an issue: GitHub.