{"record":{"id":"eb3a14be0408b621","repo":"lionsoul2014/ip2region","slug":"incomplete-read-rbytes-read-stats-size-exp","errorCode":null,"errorMessage":"incomplete read (${rBytes} read, ${stats.size} expected)","messagePattern":"incomplete read \\((.+?) read, (.+?) expected\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"binding/javascript/util.js","lineNumber":376,"sourceCode":"    if (rBytes != vBytes) {\n        throw new Error(`incomplete read (${rBytes} read, ${vBytes} expected)`);\n    }\n    return buffer;\n}\n\nexport function loadVectorIndexFromFile(dbPath) {\n    const fd = fs.openSync(dbPath, \"r\");\n    const vIndex = loadVectorIndex(fd);\n    fs.closeSync(fd);\n    return vIndex;\n}\n\nexport function loadContent(fd) {\n    const stats = fs.fstatSync(fd);\n    const buffer = Buffer.alloc(stats.size);\n    const rBytes = fs.readSync(fd, buffer, 0, buffer.length, 0);\n    if (rBytes != stats.size) {\n        throw new Error(`incomplete read (${rBytes} read, ${stats.size} expected)`);\n    }\n    return buffer;\n}\n\nexport function loadContentFromFile(dbPath) {\n    const fd = fs.openSync(dbPath, \"r\");\n    const content = loadContent(fd);\n    fs.closeSync(fd);\n    return content;\n}\n\n// --- \n\n// Verify if the current Searcher could be used to search the specified xdb file.\n// Why do we need this check ?\n// The future features of the xdb impl may cause the current searcher not able to work properly.\n//\n// @Note: You Just need to check this ONCE when the service starts","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/lionsoul2014/ip2region/blob/c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1/binding/javascript/util.js#L358-L394","documentation":"loadContent stats the fd and reads the entire file (stats.size bytes) from offset 0 into one Buffer for the ContentCache policy. If the read returns fewer bytes than fstat reported, the library throws rather than caching an incomplete copy of the data region.","triggerScenarios":"loadContent(fd) / content() where the file shrinks between fstatSync and readSync (concurrent writer/replacer), a truncated file, or I/O returning short reads on an unreliable/network filesystem.","commonSituations":"Deploy systems that swap the .xdb via rename while searchers hold open fds; NFS/EFS hiccups; file being regenerated by the xdb maker while the app starts.","solutions":["Re-copy the xdb file, verify integrity (size/checksum), and restart or reload the searcher.","Stop concurrent writers before loading, or atomically swap via rename and reopen the fd after.","Retry the load — a transient short read often succeeds on the second attempt.","Add a pre-check comparing fstatSync(fd).size against the minimum expected xdb size."],"exampleFix":"// before\nconst buf = loadContent(fd); // short read -> throws\n// after\nlet buf;\nfor (let i = 0; i < 3 && !buf; i++) {\n  try { buf = loadContent(fd); } catch (e) { if (!/incomplete read/.test(e.message)) throw e; }\n}\nif (!buf) throw new Error('xdb content repeatedly short-read; file may be truncated');","handlingStrategy":"retry","validationCode":"const size = fs.fstatSync(fd).size;\nif (size === 0) throw new Error('xdb file is empty');\n// optionally: minimum plausible size check before full-content cache load","typeGuard":null,"tryCatchPattern":"try {\n  contentBuf = loadContent(fd);\n} catch (e) {\n  if (String(e.message).includes('incomplete read')) {\n    // reopen the file (it may have been swapped) and retry once\n    fd = fs.openSync(dbPath, 'r');\n    contentBuf = loadContent(fd);\n  } else throw e;\n}","preventionTips":["Deploy xdb updates atomically (write temp file + rename) and reopen fds after swap.","Avoid loading content cache while the maker writes the same path.","Monitor disk/filesystem health for network mounts serving the db."],"tags":["nodejs","file-io","concurrency","truncated-file"],"backgroundTag":"incomplete-file-read","analyzedSha":"c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1","analyzedAt":"2026-09-02T16:58:39.988Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}